Spring Boot aplikazio baterako Docker Irudi optimizatuak eraikitzea

Edukiontziak aplikazio bat bere software eta sistema eragilearen menpekotasun guztiekin ontziratzeko baliabiderik hobetsi bihurtu dira eta gero ingurune ezberdinetara entregatzeko.

Artikulu honek Spring Boot aplikazio bat edukiontziratzeko modu desberdinak biltzen ditu:

  • Docker irudi bat eraikitzea dockerfile bat erabiliz,
  • Iturburutik OCI irudi bat eraikitzea Cloud-Native Buildpack erabiliz,
  • eta irudien optimizazioa exekuzioan JAR zatiak maila ezberdinetan bereiziz geruzadun tresnak erabiliz.

 Kode Adibidea

Artikulu honek lan-kodearen adibide batekin batera doa GitHub-en .

Edukiontziaren terminologia

Artikuluan zehar erabilitako edukiontziaren terminologiarekin hasiko gara:

  • Edukiontziaren irudia: formatu zehatz bateko fitxategia. Gure aplikazioa edukiontzi-irudi bihurtzen dugu eraikitze-tresna exekutatuz.
  • edukiontzi: edukiontziaren irudiaren instantzia exekutagarria.
  • Edukiontzi motorra: edukiontzia exekutatzeko ardura duen deabru-prozesua.
  • Edukiontziaren ostalaria: edukiontzi-motorra martxan dagoen makina ostalaria.
  • Edukiontzien erregistroa: edukiontziaren irudia argitaratzeko eta banatzeko erabiltzen den kokapen orokorra.
  • OCI estandarraEdukiontzi Irekiaren Ekimena (OCI) Linux Fundazioak eratutako kode irekiko kudeaketa-esparru arina da. OCI Irudien Zehaztapenak industriako estandarrak definitzen ditu edukiontzien irudi formatuen eta exekuzio-denbora, edukiontzi-motor guztiek edozein eraikuntza tresnak sortutako edukiontzien irudiak exekutatu ditzaketela ziurtatzeko.

Aplikazio bat edukiontziratzeko, gure aplikazioa edukiontzi-irudi batean biltzen dugu eta irudi hori erregistro publikoan argitaratzen dugu. Edukiontziaren exekuzio-denborak irudi hau erregistrotik berreskuratzen du, deskonprimitu eta aplikazioa bere barruan exekutatzen du.

Spring Boot-en 2.3 bertsioak OCI irudiak eraikitzeko pluginak eskaintzen ditu.

Docker gehien erabiltzen den edukiontziaren inplementazioa da, eta Docker erabiltzen dugu gure adibideetan, beraz, artikulu honetako ondorengo edukiontzien erreferentzia guztiak Docker-era aipatuko dira.

Edukiontziaren irudia modu tradizionalean eraikitzea

Spring Boot aplikazioetarako Docker irudiak sortzea oso erraza da zure Dockerfile-ra argibide batzuk gehituta.

Lehenik eta behin, JAR exekutagarri bat sortzen dugu eta, Dockerfile argibideen zati gisa, JAR exekutagarria oinarrizko JRE irudiaren gainean kopiatu behar dugu beharrezko pertsonalizazioak aplikatu ondoren.

Sortu dezagun gure Spring aplikazioa Udaberriko Initializr mendekotasunekin weblombokΠΈ actuator. Gainera, atseden kontrolagailu bat gehitzen dugu API bat eskaintzeko GETmetodoa.

Dockerfile bat sortzea

Ondoren, aplikazio hau edukiontzi batean jartzen dugu gehituz Dockerfile:

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

Gure Dockerfile-k oinarrizko irudi bat dauka adoptopenjdk, horren gainean gure JAR fitxategia kopiatzen dugu eta gero portua irekitzen dugu, 8080eskaerak entzungo dituena.

Aplikazioen muntaia

Lehenik eta behin aplikazio bat sortu behar duzu Maven edo Gradle erabiliz. Hemen Maven erabiltzen ari gara:

mvn clean package

Honek JAR fitxategi exekutagarri bat sortzen du aplikaziorako. JAR exekutagarri hau Docker irudi batean bihurtu behar dugu Docker motorra exekutatzeko.

Sortu edukiontziaren irudia

Ondoren, JAR exekutagarri hau Docker irudian jartzen dugu komandoa exekutatuz docker buildLehenago sortutako Dockerfile-a duen proiektuaren erro-direktoriotik:

docker build  -t usersignup:v1 .

Gure irudia zerrendan ikus dezakegu komandoarekin:

docker images 

Goiko komandoaren irteerak gure irudia barne hartzen du usersignupoinarrizko irudiarekin batera, adoptopenjdkgure Dockerfile-n zehaztuta.

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

Ikusi edukiontzi-irudi baten barruko geruzak

Ikus dezagun irudiaren barruko geruza pila. Erabiliko dugu tresna  urperatu, geruza hauek ikusteko:

dive usersignup:v1

Hona hemen Dive komandoaren irteeraren zati bat: 

Spring Boot aplikazio baterako Docker Irudi optimizatuak eraikitzea

Ikus dezakegunez, aplikazio geruzak irudiaren tamainaren zati garrantzitsu bat osatzen du. Geruza honen tamaina murriztu nahi dugu hurrengo ataletan gure optimizazioaren zati gisa.

Edukiontzi-irudia eraikitzea Buildpack-ekin

Muntaketa paketeak (Eraikitzeko paketeak) Platform as a Service (PAAS) eskaintzak erabiltzen duten termino generikoa da iturburu-kodetik edukiontzi-irudia sortzeko. Herokuk 2011n jarri zuen abian eta harrezkero Cloud Foundry, Google App Engine, Gitlab, Knative eta beste batzuek hartu dute.

Spring Boot aplikazio baterako Docker Irudi optimizatuak eraikitzea

Cloud Build paketeen abantaila

Irudiak eraikitzeko Buildpack erabiltzearen abantaila nagusietako bat hori da irudien konfigurazio-aldaketak zentralki kudeatu daitezke (eraikitzailea) eta aplikazio guztietara hedatu eraikitzailea erabiliz.

Eraikitzeko paketeak plataformari estu lotuta zeuden. Cloud-Native Buildpack-ek plataforma guztietan estandarizazioa eskaintzen du OCI irudi formatua onartzen duelarik, eta horrek bermatzen du irudia Docker motorrak exekutatu ahal izango duela.

Spring Boot Plugin-a erabiliz

Spring Boot pluginak OCI irudiak sortzen ditu iturburutik Buildpack erabiliz. Irudiak erabiliz sortzen dira bootBuildImagezereginak (Gradle) edo spring-boot:build-imagexede (Maven) eta Docker instalazio lokala.

Docker erregistrora bidali behar dugun irudiaren izena pertsonaliza dezakegu izena zehaztuz 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>

Erabili dezagun Maven exekutatzeko build-imageaplikazio bat sortzeko eta edukiontziaren irudia sortzeko helburuak. Une honetan ez dugu Dockerfilerik erabiltzen ari.

mvn spring-boot:build-image

Emaitza honelakoa izango da:

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

Irteeratik, hori ikusten dugu paketo Cloud-Native buildpackfuntzionatzen duen OCI irudia sortzeko erabiltzen da. Lehen bezala, Docker irudi gisa zerrendatutako irudia ikus dezakegu komandoa exekutatuz:

docker images 

Ondorioa:

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

Edukiontzi-irudia sortzea Jib-ekin

Jib Google-ren irudiak sortzeko plugin bat da, edukiontzi-irudia iturritik sortzeko metodo alternatibo bat eskaintzen duena.

konfiguratzea jib-maven-pluginpom.xml-n:

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

Ondoren, Jib plugina exekutatzen dugu Maven komandoa erabiliz aplikazioa eraikitzeko eta edukiontziaren irudia sortzeko. Lehen bezala, hemen ez dugu Dockerfilerik erabiltzen ari:

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

Goiko Maven komandoa exekutatu ondoren, irteera hau lortuko dugu:

[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

Irteerak erakusten du edukiontziaren irudia sortu eta erregistroan jarri dela.

Irudi optimizatuak sortzeko motibazioak eta metodoak

Bi arrazoi nagusi ditugu optimizatzeko:

  • produktibitatea: Edukiontzien orkestrazio sistema batean, edukiontzi-irudi bat irudi-erregistrotik ateratzen da edukiontzi-motorra exekutatzen duen ostalarira. Prozesu honi plangintza deitzen zaio. Erregistrotik irudi handiak ateratzeak edukiontzien orkestrazio sistemetan programazio denbora luzeak eta CI kanalizazioetan eraikitzeko denbora luzeak eragiten ditu.
  • Π‘Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ: irudi handiek ere ahultasunetarako eremu handia dute.

Docker irudi bat geruza pila batez osatuta dago, bakoitza gure Dockerfileko adierazpen bat adierazten duena. Geruza bakoitzak azpiko geruzaren aldaketen delta adierazten du. Docker-eko irudi bat erregistrotik ateratzen dugunean, geruzetan ateratzen da eta ostalarian gordetzen da.

Spring Boot erabilerak "pote lodi" barruan bilketa formatu lehenetsi gisa. JAR lodi bati begiratzen diogunean, aplikazioa JAR osoaren zati oso txikia dela ikusten dugu. Hau da gehien aldatzen den zatia. Gainerakoa Spring Framework menpekotasunek osatzen dute.

Optimizazio formula aplikazioa Spring Framework menpekotasunetatik bereizitako maila batean isolatzean oinarritzen da.

JAR fitxategi lodiaren zatirik handiena osatzen duen mendekotasun-geruza behin bakarrik deskargatzen da eta sistema ostalarian gordetzen da.

Aplikazioaren geruza fin bat bakarrik ateratzen da aplikazioen eguneratzeetan eta edukiontzien programazioan. diagrama honetan agertzen den bezala:

Spring Boot aplikazio baterako Docker Irudi optimizatuak eraikitzea

Hurrengo ataletan, Spring Boot aplikazio baterako irudi optimizatu hauek nola sortu ikusiko dugu.

Spring Boot aplikazio baterako edukiontzi irudi optimizatua eraikitzea Buildpack-ekin

Spring Boot 2.3-k geruzak onartzen ditu JAR fitxategi lodi baten zatiak geruza bereizietan ateraz. Geruzak egiteko funtzioa lehenespenez desgaituta dago eta esplizituki gaituta egon behar da Spring Boot Maven plugina erabiliz:

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

Konfigurazio hau erabiliko dugu gure edukiontziaren irudia eraikitzeko lehenengo Buildpack-ekin eta gero Docker-ekin hurrengo ataletan.

Goazen korrika build-imageMaven helburua edukiontzi irudi bat sortzeko:

mvn spring-boot:build-image

Dive exekutatzen badugu emaitzako irudiko geruzak ikusteko, aplikazioaren geruza (gorriz inguratuta) askoz txikiagoa dela kilobyte barrutian ikusiko dugu JAR formatu lodia erabiliz lortu dugunarekin alderatuta:

Spring Boot aplikazio baterako Docker Irudi optimizatuak eraikitzea

Spring Boot aplikazio baterako edukiontzi irudi optimizatua eraikitzea Docker-ekin

Maven edo Gradle plugin bat erabili beharrean, geruzadun Docker JAR irudi bat ere sor dezakegu Docker fitxategi batekin.

Docker erabiltzen dugunean, bi urrats gehiago eman behar ditugu geruzak ateratzeko eta azken irudian kopiatzeko.

Maven-ekin geruzak gaituta eraiki ondoren sortutako JAR-aren edukiak itxura hau izango du:

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

Irteerak izeneko JAR gehigarri bat erakusten du spring-boot-jarmode-layertoolsΠΈ layersfle.idxfitxategia. JAR fitxategi gehigarri honek geruzak egiteko gaitasunak eskaintzen ditu, hurrengo atalean azaltzen den moduan.

Atera menpekotasunak geruza bereizietan

Geruzak gure JAR geruzetatik ikusteko eta ateratzeko, sistemaren propietatea erabiltzen dugu -Djarmode=layertoolshasteko spring-boot-jarmode-layertoolsJAR aplikazioaren ordez:

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

Komando hau exekutatzeak eskuragarri dauden komando-aukerak dituen irteera bat sortzen du:

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

Irteerak komandoak erakusten ditu listextractΠΈ helpс helplehenetsia izan. Exekutatu dezagun komandoa listaukera:

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

Geruza gisa gehi daitezkeen mendekotasunen zerrenda ikusten dugu.

Geruzak lehenespenez:

Geruzaren izena

Edukia

dependencies

bertsioak SNAPSHOT ez duen edozein mendekotasun

spring-boot-loader

JAR Loader Klaseak

snapshot-dependencies

bertsioak SNAPSHOT duen edozein mendekotasuna

application

aplikazio klaseak eta baliabideak

Geruzak urtean definitzen dira layers.idxfitxategia Docker irudian gehitu behar diren ordenan. Geruza hauek cachean gordetzen dira ostalarian lehen eskuraketaren ondoren, ez direlako aldatzen. Aplikazio-geruza eguneratua soilik deskargatzen da ostalarira, eta hori azkarragoa da tamaina murriztua dela eta .

Irudi bat eraikitzea geruza bereizietan ateratako mendekotasunak dituena

Azken irudia bi urratsetan eraikiko dugu izeneko metodoa erabiliz etapa anitzeko muntaia . Lehenengo urratsean mendekotasunak aterako ditugu eta bigarren urratsean ateratako mendekotasunak azkenera kopiatuko ditugu.

Aldatu dezagun gure Dockerfile etapa anitzeko eraikuntza baterako:

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

Konfigurazio hau aparteko fitxategi batean gordetzen dugu - Dockerfile2.

Docker irudia eraikitzen dugu komandoa erabiliz:

docker build -f Dockerfile2 -t usersignup:v1 .

Komando hau exekutatu ondoren, irteera hau lortuko dugu:

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

Ikus dezakegu Docker irudia irudi ID batekin sortu eta gero etiketatuta dagoela.

Azkenik, Dive komandoa lehen bezala exekutatzen dugu sortutako Docker irudiaren barruko geruzak egiaztatzeko. Irudi ID edo etiketa bat eman dezakegu Dive komandoaren sarrera gisa:

dive userssignup:v1

Irteeran ikus dezakezun bezala, aplikazioa duen geruza 11 KB baino ez da orain eta mendekotasunak geruza bereizietan gordetzen dira. 

Spring Boot aplikazio baterako Docker Irudi optimizatuak eraikitzea

Atera barne-menpekotasunak geruza bereizietan

Aplikazio-geruzaren tamaina gehiago murriztu dezakegu gure menpekotasun pertsonalizatuetako edozein geruza bereizi batean ateraz, aplikazioarekin ontziratu beharrean, deklaratuz. ymlizeneko antzeko fitxategia 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/"

Fitxategi honetan layers.idxizeneko menpekotasun pertsonalizatu bat gehitu dugu, io.myorgbiltegi partekatutik berreskuratutako erakunde-menpekotasunak dituena.

Irteera

Artikulu honetan, Cloud-Native Buildpacks erabiltzea aztertu dugu edukiontzi-irudia zuzenean iturburutik eraikitzeko. Hau Docker erabiltzearen alternatiba bat da edukiontzi-irudia ohiko moduan sortzeko: lehenik eta behin, JAR fitxategi exekutagarri lodi bat sortzen da eta, ondoren, edukiontzi-irudi batean paketatzen da Dockerfileko argibideak zehaztuz.

Gure edukiontzia optimizatzea ere aztertu dugu, ostalarian cachean gordetzen diren geruza bereizietan mendekotasunak ateratzen dituen geruza-funtzio bat sartuz eta edukiontziaren exekuzio-motorretan programazio garaian aplikazio geruza fin bat kargatzen da.

Artikuluan erabilitako iturburu-kode guztia helbidean aurki dezakezu Github .

Komando Erreferentzia

Hona hemen artikulu honetan erabili ditugun komandoen laburpena erreferentzia azkar bat izateko.

Testuinguruaren garbiketa:

docker system prune -a

Edukiontzi-irudia eraikitzea Dockerfile batekin:

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

Eraiki edukiontziaren irudia iturburutik (Dockerfile gabe):

mvn spring-boot:build-image

Ikusi menpekotasun-geruzak. Aplikazio jar fitxategia eraiki aurretik, ziurtatu geruzak egiteko funtzioa gaituta dagoela spring-boot-maven-plugin-en:

java -Djarmode=layertools -jar application.jar list

Atera menpekotasun geruzak. Aplikazio jar fitxategia eraiki aurretik, ziurtatu geruzak egiteko funtzioa gaituta dagoela spring-boot-maven-plugin-en:

 java -Djarmode=layertools -jar application.jar extract

Edukiontzien irudien zerrenda ikustea

docker images

Ikusi edukiontziaren irudiaren barruan ezkerrean (ziurtatu urpekaritza tresna instalatuta dagoela):

dive <image ID or image tag>

Iturria: www.habr.com