Ustvarjanje optimiziranih slik Docker za spomladansko zagonsko aplikacijo

Vsebniki so postali prednostno sredstvo za pakiranje aplikacije z vso njeno programsko opremo in odvisnostmi operacijskega sistema ter njihovo nato dostavo v različna okolja.

Ta članek pokriva različne načine za shranjevanje aplikacije Spring Boot:

  • ustvarjanje slike Docker z uporabo datoteke Docker,
  • ustvarjanje slike OCI iz vira z uporabo Cloud-Native Buildpack,
  • in optimizacijo slike med izvajanjem z ločevanjem delov JAR v različne plasti z uporabo večplastnih orodij.

 Vzorčna koda

Ta članek spremlja primer delujoče kode na GitHubu .

Kontejnerska terminologija

Začeli bomo s terminologijo vsebnika, uporabljeno v članku:

  • Slika vsebnika: datoteka določenega formata. Našo aplikacijo bomo pretvorili v sliko vsebnika z zagonom orodja za gradnjo.
  • posoda: Izvedljiv primerek slike vsebnika.
  • Kontejnerski motor: demonski proces, odgovoren za izvajanje vsebnika.
  • Gostitelj vsebnika: gostiteljski računalnik, na katerem teče motor vsebnika.
  • Register zabojnikov: splošna lokacija, ki se uporablja za objavo in distribucijo slike vsebnika.
  • OCI standardPobuda za odprti zabojnik (OCI) je lahka, odprta struktura upravljanja, oblikovana znotraj Linux Foundation. Specifikacija slike OCI določa industrijske standarde za formate slike vsebnika in izvajalnega okolja, da zagotovi, da lahko vsi motorji vsebnika izvajajo slike vsebnika, ustvarjene s katerim koli orodjem za gradnjo.

Za shranjevanje aplikacije v vsebnik zavijemo našo aplikacijo v sliko vsebnika in to sliko objavimo v skupnem registru. Izvajalno okolje vsebnika pridobi to sliko iz registra, jo razpakira in zažene aplikacijo v njej.

Različica 2.3 programa Spring Boot ponuja vtičnike za ustvarjanje slik OCI.

Lučki delavec je najpogosteje uporabljena izvedba vsebnika, v naših primerih pa uporabljamo Docker, zato se bodo vse nadaljnje reference vsebnika v tem članku nanašale na Docker.

Gradnja slike vsebnika na tradicionalen način

Ustvarjanje slik Docker za aplikacije Spring Boot je zelo preprosto z dodajanjem nekaj navodil v datoteko Docker.

Najprej ustvarimo izvedljivo datoteko JAR in kot del navodil za datoteko Docker kopiramo izvršljivo datoteko JAR na vrh osnovne slike JRE, potem ko uporabimo potrebne nastavitve.

Ustvarimo našo aplikacijo Spring on Inicializacija pomladi z odvisnostmi weblombokи actuator. Dodajamo tudi krmilnik za počitek, ki zagotavlja API GETmetoda.

Ustvarjanje datoteke Docker

Nato to aplikacijo pospravimo v kontejner z dodajanjem Dockerfile:

FROM adoptopenjdk:11-jre-hotspot
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/application.jar"]

Naša datoteka Docker vsebuje osnovno sliko iz adoptopenjdk, na katerega prekopiramo našo datoteko JAR in nato odpremo vrata, 8080ki bo poslušal zahteve.

Gradnja aplikacije

Najprej morate ustvariti aplikacijo z Maven ali Gradle. Tukaj uporabljamo Maven:

mvn clean package

To ustvari izvršljivo datoteko JAR za aplikacijo. To izvršljivo datoteko JAR moramo pretvoriti v sliko Docker, da se bo izvajala na motorju Docker.

Ustvarjanje slike vsebnika

To izvršljivo datoteko JAR nato vstavimo v sliko Dockerja tako, da zaženemo ukaz docker buildiz korenskega imenika projekta, ki vsebuje prej ustvarjeno datoteko Docker:

docker build  -t usersignup:v1 .

Našo sliko lahko vidimo na seznamu z ukazom:

docker images 

Izhod zgornjega ukaza vključuje našo sliko usersignupskupaj z osnovno sliko, adoptopenjdkdoločeno v naši datoteki Docker.

REPOSITORY          TAG                 SIZE
usersignup          v1                  249MB
adoptopenjdk        11-jre-hotspot      229MB

Oglejte si plasti znotraj slike vsebnika

Poglejmo kup plasti znotraj slike. Bomo uporabili Orodje  potapljanje za ogled teh plasti:

dive usersignup:v1

Tukaj je del izhoda ukaza Dive: 

Ustvarjanje optimiziranih slik Docker za spomladansko zagonsko aplikacijo

Kot lahko vidimo, sloj aplikacije predstavlja pomemben del velikosti slike. V naslednjih razdelkih želimo zmanjšati velikost te plasti kot del naše optimizacije.

Ustvarjanje slike vsebnika z uporabo Buildpack

Montažni paketi (Buildpacks) je splošni izraz, ki ga uporabljajo različne ponudbe platforme kot storitve (PAAS) za ustvarjanje slike vsebnika iz izvorne kode. Leta 2011 ga je lansiral Heroku, od takrat pa so ga sprejeli Cloud Foundry, Google App Engine, Gitlab, Knative in številni drugi.

Ustvarjanje optimiziranih slik Docker za spomladansko zagonsko aplikacijo

Prednost paketov za gradnjo v oblaku

Ena od glavnih prednosti uporabe Buildpacka za ustvarjanje slik je ta Spremembe konfiguracije slike je mogoče upravljati centralno (builder) in jih razširiti na vse aplikacije z graditeljem.

Gradbeni paketi so bili tesno povezani s platformo. Cloud-Native Buildpacks zagotavljajo standardizacijo na različnih platformah s podporo formata slike OCI, ki zagotavlja, da lahko sliko izvaja mehanizem Docker.

Uporaba vtičnika Spring Boot

Vtičnik Spring Boot gradi slike OCI iz vira z uporabo Buildpack. Slike so ustvarjene z uporabo bootBuildImageopravil (Gradle) oz spring-boot:build-imagecilji (Maven) in lokalna namestitev Dockerja.

Prilagodimo lahko ime slike, ki jo je treba potisniti v register Docker, tako da vnesemo ime image tag:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    <image>
      <name>docker.io/pratikdas/${project.artifactId}:v1</name>
    </image>
  </configuration>
</plugin>

Za to uporabimo Maven build-imagecilji za ustvarjanje aplikacije in ustvarjanje slike vsebnika. Trenutno ne uporabljamo nobenih datotek Docker.

mvn spring-boot:build-image

Rezultat bo nekaj takega:

[INFO] --- spring-boot-maven-plugin:2.3.3.RELEASE:build-image (default-cli) @ usersignup ---
[INFO] Building image 'docker.io/pratikdas/usersignup:v1'
[INFO] 
[INFO]  > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 0%
.
.
.. [creator]     Adding label 'org.springframework.boot.version'
.. [creator]     *** Images (c311fe74ec73):
.. [creator]           docker.io/pratikdas/usersignup:v1
[INFO] 
[INFO] Successfully built image 'docker.io/pratikdas/usersignup:v1'

Iz izhoda to vidimo paketo Cloud-Native buildpackuporablja za ustvarjanje delujoče slike OCI. Tako kot prej lahko vidimo sliko, navedeno kot Dockerjeva slika, tako da zaženemo ukaz:

docker images 

Zaključek:

REPOSITORY                             SIZE
paketobuildpacks/run                  84.3MB
gcr.io/paketo-buildpacks/builder      652MB
pratikdas/usersignup                  257MB

Ustvarjanje slike vsebnika z uporabo Jiba

Jib je Googlov vtičnik za ustvarjanje slik, ki ponuja alternativno metodo za ustvarjanje slike vsebnika iz izvorne kode.

Konfiguriranje jib-maven-pluginv pom.xml:

      <plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>jib-maven-plugin</artifactId>
        <version>2.5.2</version>
      </plugin>

Nato zaženemo vtičnik Jib z ukazom Maven, da zgradimo aplikacijo in ustvarimo sliko vsebnika. Kot prej tukaj ne uporabljamo nobenih datotek Docker:

mvn compile jib:build -Dimage=<docker registry name>/usersignup:v1

Po izvedbi zgornjega ukaza Maven dobimo naslednji rezultat:

[INFO] Containerizing application to pratikdas/usersignup:v1...
.
.
[INFO] Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, io.pratik.users.UsersignupApplication]
[INFO] 
[INFO] Built and pushed image as pratikdas/usersignup:v1
[INFO] Executing tasks:
[INFO] [==============================] 100.0% complete

Izhod kaže, da je bila slika vsebnika ustvarjena in postavljena v register.

Motivacije in tehnike za ustvarjanje optimiziranih slik

Za optimizacijo imamo dva glavna razloga:

  • Produktivnost: V sistemu za orkestracijo vsebnika se slika vsebnika pridobi iz registra slik v gostitelja, ki izvaja motor vsebnika. Ta proces se imenuje načrtovanje. Vlečenje velikih slik iz registra povzroči dolge čase načrtovanja v sistemih za orkestracijo vsebnikov in dolge čase gradnje v cevovodih CI.
  • varnost: Večje slike imajo tudi večjo površino za ranljivosti.

Slika Docker je sestavljena iz niza plasti, od katerih vsaka predstavlja navodilo v naši datoteki Docker. Vsaka plast predstavlja delto sprememb v spodnji plasti. Ko potegnemo sliko Dockerja iz registra, se povleče v plasteh in shrani v predpomnilnik na gostitelju.

Spring Boot uporablja "fat JAR" v kot privzeti format pakiranja. Ko pogledamo debel JAR, vidimo, da aplikacija predstavlja zelo majhen del celotnega JAR-a. To je del, ki se najpogosteje spreminja. Preostanek sestavljajo odvisnosti Spring Framework.

Formula optimizacije se osredotoča na izolacijo aplikacije na ločeni ravni od odvisnosti Spring Framework.

Plast odvisnosti, ki tvori večji del debele datoteke JAR, se prenese samo enkrat in shrani v predpomnilnik v gostiteljskem sistemu.

Med posodobitvami aplikacij in razporejanjem vsebnika se potegne le tanka plast aplikacije. kot je prikazano v tem diagramu:

Ustvarjanje optimiziranih slik Docker za spomladansko zagonsko aplikacijo

V naslednjih razdelkih si bomo ogledali, kako ustvariti te optimizirane slike za aplikacijo Spring Boot.

Ustvarjanje optimizirane slike vsebnika za spomladansko zagonsko aplikacijo z uporabo Buildpack

Spring Boot 2.3 podpira plastenje z ekstrakcijo delov debele datoteke JAR v ločene plasti. Funkcija slojevanja je privzeto onemogočena in jo je treba izrecno omogočiti z uporabo vtičnika Spring Boot Maven:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    <layers>
      <enabled>true</enabled>
    </layers>
  </configuration> 
</plugin>

To konfiguracijo bomo uporabili za izdelavo naše slike vsebnika najprej z Buildpackom in nato z Dockerjem v naslednjih razdelkih.

Zaženimo build-imageCilj Maven za ustvarjanje slike vsebnika:

mvn spring-boot:build-image

Če zaženemo Dive, da vidimo plasti na dobljeni sliki, lahko vidimo, da je aplikacijska plast (obrobljena z rdečo) veliko manjša v obsegu kilobajtov v primerjavi s tistim, kar smo dobili z debelim formatom JAR:

Ustvarjanje optimiziranih slik Docker za spomladansko zagonsko aplikacijo

Ustvarjanje optimizirane slike vsebnika za spomladansko zagonsko aplikacijo z uporabo Dockerja

Namesto uporabe vtičnika Maven ali Gradle lahko ustvarimo večplastno sliko Docker JAR z datoteko Docker.

Ko uporabljamo Docker, moramo izvesti dva dodatna koraka, da ekstrahiramo plasti in jih kopiramo v končno sliko.

Vsebina dobljene datoteke JAR po gradnji z uporabo programa Maven z omogočenim slojevanjem bo videti takole:

META-INF/
.
BOOT-INF/lib/
.
BOOT-INF/lib/spring-boot-jarmode-layertools-2.3.3.RELEASE.jar
BOOT-INF/classpath.idx
BOOT-INF/layers.idx

Izhod prikazuje dodatno JAR z imenom spring-boot-jarmode-layertoolsи layersfle.idxmapa. Ta dodatna datoteka JAR zagotavlja zmožnosti večplastne obdelave, kot je opisano v naslednjem razdelku.

Ekstrahiranje odvisnosti na posameznih slojih

Za ogled in ekstrahiranje slojev iz večplastnega JAR-ja uporabljamo sistemsko lastnost -Djarmode=layertoolsza začetek spring-boot-jarmode-layertoolsJAR namesto aplikacije:

java -Djarmode=layertools -jar target/usersignup-0.0.1-SNAPSHOT.jar

Zagon tega ukaza ustvari izpis, ki vsebuje razpoložljive ukazne možnosti:

Usage:
  java -Djarmode=layertools -jar usersignup-0.0.1-SNAPSHOT.jar

Available commands:
  list     List layers from the jar that can be extracted
  extract  Extracts layers from the jar for image creation
  help     Help about any command

Izhod prikazuje ukaze listextractи helpс helpbiti privzeto. Zaženimo ukaz z listmožnost:

java -Djarmode=layertools -jar target/usersignup-0.0.1-SNAPSHOT.jar list
dependencies
spring-boot-loader
snapshot-dependencies
application

Vidimo seznam odvisnosti, ki jih je mogoče dodati kot plasti.

Privzeti sloji:

Ime sloja

Vsebina

dependencies

katera koli odvisnost, katere različica ne vsebuje SNAPSHOT

spring-boot-loader

Razredi nalagalnika JAR

snapshot-dependencies

katera koli odvisnost, katere različica vsebuje SNAPSHOT

application

aplikacijski razredi in viri

Plasti so definirane v layers.idxdatoteko v vrstnem redu, kot naj bodo dodani sliki Docker. Ti sloji so predpomnjeni v gostitelju po prvem priklicu, ker se ne spremenijo. Na gostitelja se prenese samo posodobljena aplikacijska plast, ki je hitrejša zaradi zmanjšane velikosti .

Gradnja slike z odvisnostmi, ekstrahiranimi v ločene plasti

Končno sliko bomo zgradili v dveh fazah z metodo imenovano večstopenjska montaža . V prvem koraku bomo ekstrahirali odvisnosti, v drugem koraku pa kopirali ekstrahirane odvisnosti v končno sliko.

Spremenimo našo datoteko Dockerfile za večstopenjsko gradnjo:

# the first stage of our build will extract the layers
FROM adoptopenjdk:14-jre-hotspot as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract

# the second stage of our build will copy the extracted layers
FROM adoptopenjdk:14-jre-hotspot
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

To konfiguracijo shranimo v ločeno datoteko - Dockerfile2.

Sliko Docker zgradimo z ukazom:

docker build -f Dockerfile2 -t usersignup:v1 .

Po izvedbi tega ukaza dobimo naslednji rezultat:

Sending build context to Docker daemon  20.41MB
Step 1/12 : FROM adoptopenjdk:14-jre-hotspot as builder
14-jre-hotspot: Pulling from library/adoptopenjdk
.
.
Successfully built a9ebf6970841
Successfully tagged userssignup:v1

Vidimo lahko, da je slika Docker ustvarjena z ID-jem slike in nato označena.

Na koncu zaženemo ukaz Dive kot prej, da pregledamo plasti znotraj ustvarjene slike Docker. Kot vhod v ukaz Dive lahko zagotovimo ID slike ali oznako:

dive userssignup:v1

Kot lahko vidite v izhodu, je sloj, ki vsebuje aplikacijo, zdaj velik samo 11 KB, odvisnosti pa so predpomnjene v ločenih slojih. 

Ustvarjanje optimiziranih slik Docker za spomladansko zagonsko aplikacijo

Izločanje notranjih odvisnosti na posameznih slojih

Velikost ravni aplikacije lahko dodatno zmanjšamo tako, da ekstrahiramo vse naše odvisnosti po meri v ločeno raven, namesto da jih zapakiramo z aplikacijo tako, da jih prijavimo v ymlpodobna datoteka z imenom layers.idx:

- "dependencies":
  - "BOOT-INF/lib/"
- "spring-boot-loader":
  - "org/"
- "snapshot-dependencies":
- "custom-dependencies":
  - "io/myorg/"
- "application":
  - "BOOT-INF/classes/"
  - "BOOT-INF/classpath.idx"
  - "BOOT-INF/layers.idx"
  - "META-INF/"

V tej datoteki layers.idxdodali smo odvisnost po meri z imenom, io.myorgki vsebuje odvisnosti organizacije, pridobljene iz skupnega repozitorija.

Izhod

V tem članku smo si ogledali uporabo Cloud-Native Buildpacks za izdelavo slike vsebnika neposredno iz izvorne kode. To je alternativa uporabi Dockerja za ustvarjanje slike vsebnika na običajen način: najprej ustvarite debelo izvedljivo datoteko JAR in jo nato zapakirate v sliko vsebnika z določitvijo navodil v datoteki Docker.

Preučili smo tudi optimizacijo našega vsebnika z omogočanjem funkcije razporejanja po plasteh, ki povleče odvisnosti v ločene plasti, ki so predpomnjene na gostitelju, in tanka plast aplikacije se naloži ob času razporejanja v izvajalske mehanizme vsebnika.

Vso izvorno kodo, uporabljeno v članku, najdete na GitHub .

Referenca ukaza

Tukaj je kratek povzetek ukazov, ki smo jih uporabili v tem članku.

Čiščenje konteksta:

docker system prune -a

Ustvarjanje slike vsebnika z uporabo datoteke Docker:

docker build -f <Docker file name> -t <tag> .

Sliko vsebnika zgradimo iz izvorne kode (brez datoteke Dockerfile):

mvn spring-boot:build-image

Oglejte si sloje odvisnosti. Pred gradnjo datoteke JAR aplikacije se prepričajte, da je funkcija razslojevanja omogočena v vtičniku spring-boot-maven-plugin:

java -Djarmode=layertools -jar application.jar list

Ekstrahiranje slojev odvisnosti. Pred gradnjo datoteke JAR aplikacije se prepričajte, da je funkcija razslojevanja omogočena v vtičniku spring-boot-maven-plugin:

 java -Djarmode=layertools -jar application.jar extract

Oglejte si seznam slik vsebnika

docker images

Pogled na levi strani znotraj slike vsebnika (prepričajte se, da je orodje za potapljanje nameščeno):

dive <image ID or image tag>

Vir: www.habr.com