Optimizētu Docker attēlu izveide pavasara sāknÄ“Å”anas lietojumprogrammai

Konteineri ir kļuvuÅ”i par vēlamo lÄ«dzekli, lai iesaiņotu lietojumprogrammu ar visām programmatÅ«ras un operētājsistēmas atkarÄ«bām un pēc tam piegādātu tās dažādās vidēs.

Šajā rakstā ir aprakstīti dažādi veidi, kā ievietot Spring Boot lietojumprogrammu.

  • izveidot Docker attēlu, izmantojot Docker failu,
  • veidojot OCI attēlu no avota, izmantojot Cloud-Native Buildpack,
  • un attēla optimizācija izpildes laikā, sadalot JAR daļas dažādos lÄ«meņos, izmantojot slāņveida rÄ«kus.

 Koda piemērs

Å im rakstam ir pievienots darba koda piemērs vietnē GitHub .

Konteineru terminoloģija

Sāksim ar konteinera terminoloģiju, kas izmantota visā rakstā:

  • Konteinera attēls: noteikta formāta fails. Mēs pārvērÅ”am savu lietojumprogrammu par konteinera attēlu, palaižot veidoÅ”anas rÄ«ku.
  • Konteiners: konteinera attēla izpildāms gadÄ«jums.
  • Konteineru dzinējs: dēmona process, kas ir atbildÄ«gs par konteinera palaiÅ”anu.
  • Konteinera saimnieks: saimniekdators, kurā darbojas konteinera dzinējs.
  • Konteineru reÄ£istrs: vispārÄ«gā atraÅ”anās vieta, kas tiek izmantota konteinera attēla publicÄ“Å”anai un izplatÄ«Å”anai.
  • OCI standartsOpen Container Initiative (OCI) ir viegls, atvērtā koda pārvaldÄ«bas ietvars, ko veido Linux fonds. OCI attēla specifikācija nosaka nozares standartus konteinera attēlu formātiem un izpildlaikam, lai nodroÅ”inātu, ka visi konteineru dzinēji var palaist konteinera attēlus, kas izveidoti ar jebkuru veidoÅ”anas rÄ«ku.

Lai konteinerizētu lietojumprogrammu, mēs iesaiņojam savu lietojumprogrammu konteinera attēlā un publicējam Å”o attēlu publiskajā reÄ£istrā. Konteinera izpildlaiks izgÅ«st Å”o attēlu no reÄ£istra, izpako to un palaiž tajā esoÅ”o lietojumprogrammu.

Spring Boot versijā 2.3 ir pieejami spraudņi OCI attēlu veidoÅ”anai.

dokers ir visbiežāk izmantotā konteinera ievieÅ”ana, un savos piemēros mēs izmantojam Docker, tāpēc visas turpmākās atsauces uz konteineru Å”ajā rakstā attieksies uz Docker.

Konteinera attēla veidoÅ”ana tradicionālā veidā

Docker attēlu izveide Spring Boot lietojumprogrammām ir ļoti vienkārÅ”a, pievienojot savam Dockerfile dažus norādÄ«jumus.

Vispirms mēs izveidojam izpildāmo JAR un kā daļu no Dockerfile instrukcijām kopējam izpildāmo JAR virs pamata JRE attēla pēc nepiecieÅ”amo pielāgojumu veikÅ”anas.

Izveidosim mÅ«su pavasara pieteikumu Pavasara inicializācija ar atkarÄ«bām weblombokŠø actuator. Mēs pievienojam arÄ« atpÅ«tas kontrolieri, lai nodroÅ”inātu API GETmetodi.

Docker faila izveide

Pēc tam mēs ievietojam Å”o lietojumprogrammu konteinerā, pievienojot Dockerfile:

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

MÅ«su Dockerfile satur pamata attēlu no adoptopenjdk, virs kura mēs kopējam savu JAR failu un pēc tam atveram portu, 8080kas uzklausÄ«s pieprasÄ«jumus.

Lietojumprogrammas veidoŔana

Vispirms jums ir jāizveido lietojumprogramma, izmantojot Maven vai Gradle. Šeit mēs izmantojam Maven:

mvn clean package

Tas lietojumprogrammai izveido izpildāmu JAR failu. Mums ir jāpārvērÅ” Å”is izpildāmais JAR par Docker attēlu, lai tas darbotos Docker dzinējā.

Izveidojiet konteinera attēlu

Pēc tam mēs ievietojām Å”o JAR izpildāmo failu Docker attēlā, palaižot komandu docker buildno tā projekta saknes direktorija, kurā ir iepriekÅ” izveidots Dockerfile:

docker build  -t usersignup:v1 .

Mēs varam redzēt savu attēlu sarakstā ar komandu:

docker images 

IepriekÅ” minētās komandas izvade ietver mÅ«su attēlu usersignupkopā ar pamata attēlu, adoptopenjdknorādÄ«ts mÅ«su Dockerfile.

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

Skatīt slāņus konteinera attēlā

ApskatÄ«sim slāņu kaudzi attēla iekÅ”pusē. Mēs izmantosim instruments  nirt, lai skatÄ«tu Å”os slāņus:

dive usersignup:v1

Å eit ir daļa no komandas Dive izvades: 

Optimizētu Docker attēlu izveide pavasara sāknÄ“Å”anas lietojumprogrammai

Kā redzam, lietojumprogrammas slānis veido ievērojamu attēla lieluma daļu. Mēs vēlamies samazināt Ŕī slāņa izmēru nākamajās sadaļās kā daļu no mÅ«su optimizācijas.

Konteinera attēla izveide, izmantojot Buildpack

Montāžas paketes (Buildpacks) ir vispārÄ«gs termins, ko izmanto dažādi platformas kā pakalpojuma (PAAS) piedāvājumi, lai izveidotu konteinera attēlu no pirmkoda. To palaida Heroku 2011. gadā, un kopÅ” tā laika to ir pieņēmuÅ”i Cloud Foundry, Google App Engine, Gitlab, Knative un daži citi.

Optimizētu Docker attēlu izveide pavasara sāknÄ“Å”anas lietojumprogrammai

Mākoņu veidoÅ”anas pakotņu priekÅ”rocÄ«ba

Viena no galvenajām priekÅ”rocÄ«bām, ko sniedz Buildpack izmantoÅ”ana attēlu veidoÅ”anai, ir tā attēla konfigurācijas izmaiņas var pārvaldÄ«t centralizēti (veidotājs) un izplatÄ«t visās lietojumprogrammās, izmantojot veidotāju.

BÅ«vpaketes bija cieÅ”i saistÄ«tas ar platformu. Cloud-Native Buildpacks nodroÅ”ina standartizāciju dažādās platformās, atbalstot OCI attēla formātu, kas nodroÅ”ina, ka attēlu var palaist Docker dzinējs.

Spring Boot spraudņa izmantoÅ”ana

Spring Boot spraudnis veido OCI attēlus no avota, izmantojot Buildpack. Attēli tiek veidoti, izmantojot bootBuildImageuzdevumi (Gradle) vai spring-boot:build-imagemērÄ·a (Maven) un vietējā Docker instalācija.

Mēs varam pielāgot attēla nosaukumu, kas jānosÅ«ta uz Docker reÄ£istru, norādot nosaukumu 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>

Izmantosim Maven, lai izpildÄ«tu build-imagelietojumprogrammas izveides un konteinera attēla izveides mērÄ·i. PaÅ”laik mēs neizmantojam nevienu Dockerfailu.

mvn spring-boot:build-image

Rezultāts bÅ«s apmēram Ŕāds:

[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'

No iznākuma mēs to redzam paketo Cloud-Native buildpackizmanto, lai izveidotu darba OCI attēlu. Tāpat kā iepriekÅ”, mēs varam redzēt attēlu, kas norādÄ«ts kā Docker attēls, palaižot komandu:

docker images 

Secinājums:

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

Konteinera attēla izveide, izmantojot Jib

Jib ir attēlu autorÄ“Å”anas spraudnis no Google, kas nodroÅ”ina alternatÄ«vu metodi konteinera attēla izveidei no avota.

Pielāgot jib-maven-pluginpom.xml:

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

Pēc tam mēs palaižam spraudni Jib, izmantojot komandu Maven, lai izveidotu lietojumprogrammu un izveidotu konteinera attēlu. Tāpat kā iepriekÅ”, mēs Å”eit neizmantojam nekādus Dockerfailus:

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

Pēc iepriekÅ” minētās komandas Maven izpildes mēs iegÅ«stam Ŕādu izvadi:

[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

Izvade parāda, ka konteinera attēls ir izveidots un ievietots reģistrā.

Motivācijas un metodes optimizētu attēlu veidoÅ”anai

Mums ir divi galvenie optimizācijas iemesli:

  • ŠŸŃ€Š¾ŠøŠ·Š²Š¾Š“ŠøтŠµŠ»ŃŒŠ½Š¾ŃŃ‚ŃŒ: konteinera orÄ·estrÄ“Å”anas sistēmā konteinera attēls tiek izvilkts no attēlu reÄ£istra uz resursdatoru, kurā darbojas konteinera dzinējs. Å o procesu sauc par plānoÅ”anu. Lielu attēlu izņemÅ”ana no reÄ£istra rada ilgu plānoÅ”anas laiku konteineru orÄ·estrÄ“Å”anas sistēmās un ilgus izveides laikus CI cauruļvados.
  • DroŔība: lieliem attēliem ir arÄ« liela vieta ievainojamÄ«bām.

Docker attēlu veido slāņu kaudze, un katrs no tiem attēlo paziņojumu mÅ«su Docker failā. Katrs slānis ir pamatā esoŔā slāņa izmaiņu delta. Kad mēs izvelkam Docker attēlu no reÄ£istra, tas tiek izvilkts slāņos un resursdatora keÅ”atmiņā.

Spring Boot lietojumi "resnais JAR" iekŔā kā noklusējuma iepakojuma formātu. Kad mēs skatāmies uz resno JAR, mēs redzam, ka lietojumprogramma ir ļoti maza daļa no visa JAR. Å Ä« ir tā daļa, kas mainās visvairāk. Pārējo daļu veido Spring Framework atkarÄ«bas.

Optimizācijas formula ir vērsta uz lietojumprogrammas izolÄ“Å”anu no Spring Framework atkarÄ«bām atseviŔķā lÄ«menÄ«.

AtkarÄ«bas slānis, kas veido lielāko daļu no biezā JAR faila, tiek lejupielādēts tikai vienu reizi un saglabāts resursdatora sistēmas keÅ”atmiņā.

Lietojumprogrammas atjaunināŔanas un konteinera plānoÅ”anas laikā tiek izvilkts tikai plāns lietojumprogrammas slānis. kā parādÄ«ts Å”ajā diagrammā:

Optimizētu Docker attēlu izveide pavasara sāknÄ“Å”anas lietojumprogrammai

Nākamajās sadaļās apskatÄ«sim, kā izveidot Å”os optimizētos attēlus lietojumprogrammai Spring Boot.

Optimizēta konteinera attēla izveide pavasara sāknÄ“Å”anas lietojumprogrammai, izmantojot Buildpack

Spring Boot 2.3 atbalsta slāņoÅ”anu, izvelkot bieza JAR faila daļas atseviŔķos slāņos. Slāņu funkcija pēc noklusējuma ir atspējota, un tā ir skaidri jāiespējo, izmantojot spraudni Spring Boot Maven:

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

Mēs izmantosim Å”o konfigurāciju, lai izveidotu konteinera attēlu vispirms ar Buildpack un pēc tam ar Docker nākamajās sadaļās.

Skrienam build-imageMaven mērÄ·is, lai izveidotu konteinera attēlu:

mvn spring-boot:build-image

Ja palaižam programmu Dive, lai redzētu slāņus iegūtajā attēlā, mēs varam redzēt, ka lietojumprogrammas slānis (apzīmēts ar sarkanu krāsu) ir daudz mazāks kilobaitu diapazonā, salīdzinot ar to, ko ieguvām, izmantojot biezo JAR formātu:

Optimizētu Docker attēlu izveide pavasara sāknÄ“Å”anas lietojumprogrammai

Optimizēta konteinera attēla izveide pavasara sāknÄ“Å”anas lietojumprogrammai, izmantojot Docker

Tā vietā, lai izmantotu Maven vai Gradle spraudni, mēs varam izveidot arī slāņveida Docker JAR attēlu ar Docker failu.

Kad mēs izmantojam Docker, mums ir jāveic divas papildu darbības, lai izvilktu slāņus un kopētu tos galīgajā attēlā.

IegÅ«tā JAR saturs pēc Maven izveides ar iespējotu slāņoÅ”anu izskatÄ«sies Ŕādi:

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

Izvade parāda papildu JAR ar nosaukumu spring-boot-jarmode-layertoolsŠø layersfle.idxfailu. Å is papildu JAR fails nodroÅ”ina slāņoÅ”anas iespējas, kā aprakstÄ«ts nākamajā sadaļā.

Izvilkt atkarÄ«bas no atseviŔķiem slāņiem

Lai skatÄ«tu un izvilktu slāņus no mÅ«su slāņveida JAR, mēs izmantojam sistēmas rekvizÄ«tu -Djarmode=layertoolssākumam spring-boot-jarmode-layertoolsJAR lietojumprogrammas vietā:

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

Palaižot Ŕo komandu, tiek iegūta izvade ar pieejamām komandas opcijām:

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

Izvade parāda komandas listextractŠø helpс helpbÅ«t noklusējuma. IzpildÄ«sim komandu ar listvariants:

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

Mēs redzam to atkarību sarakstu, kuras var pievienot kā slāņus.

Noklusējuma slāņi:

Slāņa nosaukums

saturs

dependencies

jebkura atkarība, kuras versija nesatur SNAPSHOT

spring-boot-loader

JAR iekrāvēju klases

snapshot-dependencies

jebkura atkarība, kuras versija satur SNAPSHOT

application

lietojumprogrammu klases un resursi

Slāņi ir definēti layers.idxfailu tādā secÄ«bā, kādā tie jāpievieno Docker attēlam. Å ie slāņi tiek saglabāti keÅ”atmiņā resursdatorā pēc pirmās ielādes, jo tie nemainās. Uz resursdatora tiek lejupielādēts tikai atjauninātais lietojumprogrammas slānis, kas ir ātrāks samazinātā izmēra dēļ .

Attēla veidoÅ”ana ar atkarÄ«bām, kas izvilktas atseviŔķos slāņos

Mēs izveidosim galÄ«go attēlu divos posmos, izmantojot metodi, ko sauc daudzpakāpju montāža . Pirmajā solÄ« mēs izgÅ«sim atkarÄ«bas, bet otrajā solÄ« mēs kopēsim iegÅ«tās atkarÄ«bas galÄ«gajā .

Modificēsim savu Dockerfile daudzpakāpju bÅ«vÄ“Å”anai:

# 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"]

Mēs saglabājam Å”o konfigurāciju atseviŔķā failā - Dockerfile2.

Mēs veidojam Docker attēlu, izmantojot komandu:

docker build -f Dockerfile2 -t usersignup:v1 .

Pēc Ŕīs komandas izpildes mēs saņemam Ŕādu izvadi:

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

Mēs redzam, ka Docker attēls tiek izveidots ar attēla ID un pēc tam tiek atzīmēts.

Visbeidzot, mēs palaižam komandu Dive tāpat kā iepriekÅ”, lai pārbaudÄ«tu Ä£enerētā Docker attēla slāņus. Mēs varam nodroÅ”ināt attēla ID vai tagu kā ievadi komandai Dive:

dive userssignup:v1

Kā redzat no izvades, slānis, kurā ir lietojumprogramma, tagad ir tikai 11 KB, un atkarÄ«bas tiek saglabātas keÅ”atmiņā atseviŔķos slāņos. 

Optimizētu Docker attēlu izveide pavasara sāknÄ“Å”anas lietojumprogrammai

Izvilkt iekŔējās atkarÄ«bas no atseviŔķiem slāņiem

Mēs varam vēl vairāk samazināt lietojumprogrammas slāņa izmēru, izvelkot jebkuru no mÅ«su pielāgotajām atkarÄ«bām atseviŔķā slānÄ«, nevis iesaiņojot tās kopā ar lietojumprogrammu, deklarējot tās ymllÄ«dzÄ«gs fails ar nosaukumu 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/"

Å ajā failā layers.idxesam pievienojuÅ”i pielāgotu atkarÄ«bu ar nosaukumu, io.myorgkas satur organizācijas atkarÄ«bas, kas izgÅ«tas no koplietotā repozitorija.

secinājums

Å ajā rakstā mēs apskatÄ«jām Cloud-Native Buildpacks izmantoÅ”anu, lai izveidotu konteinera attēlu tieÅ”i no avota. Å Ä« ir alternatÄ«va Docker izmantoÅ”anai, lai izveidotu konteinera attēlu parastajā veidā: vispirms tiek izveidots biezs izpildāms JAR fails un pēc tam tiek iesaiņots konteinera attēlā, norādot norādÄ«jumus Dockerfile.

Mēs arÄ« izskatÄ«jām sava konteinera optimizÄ“Å”anu, iekļaujot slāņoÅ”anas funkciju, kas izvelk atkarÄ«bas atseviŔķos slāņos, kas tiek saglabāti saimniekdatora keÅ”atmiņā, un plānoÅ”anas laikā konteinera izpildprogrammās tiek ielādēts plāns lietojumprogrammas slānis.

Visu rakstā izmantoto avota kodu varat atrast vietnē GitHub .

Komandu atsauce

Å eit ir sniegts Å”ajā rakstā izmantoto komandu kopsavilkums ātrai uzziņai.

Konteksta notīrīŔana:

docker system prune -a

Konteinera attēla izveide, izmantojot Dockerfile:

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

Veidot konteinera attēlu no avota (bez Dockerfile):

mvn spring-boot:build-image

Skatīt atkarības slāņus. Pirms lietojumprogrammas jar faila izveides pārliecinieties, vai spraudnī spring-boot-maven-plugin ir iespējota slāņu funkcija:

java -Djarmode=layertools -jar application.jar list

AtkarÄ«bas slāņu izvilkÅ”ana. Pirms lietojumprogrammas jar faila izveides pārliecinieties, vai spraudnÄ« spring-boot-maven-plugin ir iespējota slāņu funkcija:

 java -Djarmode=layertools -jar application.jar extract

Skatiet konteinera attēlu sarakstu

docker images

Skats kreisajā pusē konteinera attēla iekÅ”pusē (pārliecinieties, ka ir instalēts nirÅ”anas rÄ«ks):

dive <image ID or image tag>

Avots: www.habr.com