Optimeeritud Docker-piltide loomine Spring Boot rakendusele

Konteinerid on muutunud eelistatud meetodiks rakenduse koos kõigi tarkvara ja operatsioonisüsteemi sõltuvustega pakkimiseks ja seejärel erinevatesse keskkondadesse toimetamiseks.

Selles artiklis käsitletakse erinevaid Spring Boot rakenduse konteineriseerimise viise:

  • Docker'i pildi loomine Docker'i failiga,
  • OCI pildi loomine lähtekoodist Cloud-Native Buildpack'i abil,
  • ja pildi optimeerimine käitamise ajal, eraldades JAR-i osad erinevatele tasemetele mitmetasandiliste tööriistade abil.

 Koodinäide

Selle artikli juurde kuulub töötava koodi näide. GitHub'is .

Konteinerite terminoloogia

Alustame artiklis kasutatavast konteinerite terminoloogiast:

  • Konteineripilt (Container image): kindla formaadi fail. Muudame meie rakenduse konteineripildiks, käivitades kogumise tööriista.
  • Konteiner: käivitatav konteineripildi eksemplar.
  • Konteinerimootor (Container engine): demoniprotsess, mis vastutab konteineri käitamise eest.
  • Konteinerihostos (Container host): host-arvuti, millel konteerimismehhanism töötab.
  • Konteineriregistri (Container registry): üldine asukoht, mida kasutatakse konteineri pildi avaldamiseks ja levitamiseks.
  • OCI standardOpen Container Initiative (OCI) on kerge avatud haldustehnika, mis on loodud Linux Foundationi raames. OCI pildikohandamise spetsifikatsioon määratleb tööstusstandardeid konteineri pildiformaatide ja täitmisvääringute jaoks, et tagada, et kõik konteinerimehhanismid saavad käitada konteineripilte, mis on loodud mis tahes ehitusvahendi abil.

Rakenduse konteinerisse panemiseks pakime oma rakenduse konteineripildiks ja avaldame selle pildi avalikku registrisse. Konteinerite täitmisraamistik tõmbab selle pildi registrist, lahti pakib selle ja käivitab rakenduse selle sees.

Spring Boot versioon 2.3 pakub pluginaid OCI piltide loomiseks.

Docker on kõige sagedamini kasutatav konteinerite rakendus, ja kuna kasutame oma näidetes Dockerit, siis kõik edasised viidatud konteinerid selles artiklis viitavad Dockerile.

Konteineripildi loomine traditsiooniliselt

Dockeripiltide loomine Spring Boot rakenduste jaoks on väga lihtne, lisades lihtsalt mõned juhised Docker faili.

Esiteks loome JAR-faili ja Docker-faili juhistes kopeerime JAR-faili baaspildi JRE kohal pärast vajalike seadete rakendamist.

Loome oma Springi rakenduse aadressil Spring Initializr koos sõltuvustega weblombokja aktivaator. Lisame ka rest-kontrolleri, et pakkuda API-d koos GETmeetodiga.

Docker-faili loomine

Seejärel asetame selle rakenduse konteinerisse, lisades Dockerfile:

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

Meie Docker-fail sisaldab baaspilti, mille kohal on adoptopenjdk, kuhu kopeerime oma JAR-faili, ning avame seejärel sadama, 8080mis kuulab päringute eest.

Rakenduse koostamine

Esiteks tuleb rakendus luua Maveniga või Gradlega. Siin kasutame Maveni:

mvn clean package

See loob rakenduse käivitatava JAR-faili. Peame selle käivitatava JAR-i teisendama Docker-pildiks, et töötada Docker-mootoris.

Konteineri pildi loomine

Seejärel asetame selle käivitatava JAR-i Docker-pildiks, käivitades komandi docker buildprojekti juurkaustast, kus asub varem loodud Docker-fail:

docker build  -t usersignup:v1 .

Saame näha oma pilti nimekirjas käsu abil:

docker images 

Ülaltoodud käsu täitmise tulemus sisaldab meie pilti usersignupkoos aluspildiga, adoptopenjdk, mis on määratletud meie Docker failis.

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

Vaadake konteineripildi kihte

Vaadakem pilti kihist, kasutades tööriist  dive, et vaadata neid kihte:

dive usersignup:v1

Siin on osa Dive käsu täitmise tulemustest: 

Optimeeritud Docker-piltide loomine Spring Boot rakendusele

Nagu näeme, moodustab rakendustase märkimisväärse osa pildi suurusest. Tahame järgmistel osadel selle kihi suurust vähendada optimiseerimise käigus.

Konteineripildi loomine Buildpackide abil

Buildpackid (Buildpacks) — see on ühisnimi, mida kasutavad erinevad "Platvorm kui teenus" (PAAS) pakkujad konteineripildi loomiseks lähtekoodist. See käivitati 2011. aastal Heroku poolt ja on sellest ajast saanud vastuvõtuks Cloud Foundry, Google App Engine, Gitlab, Knative ja mõnede teiste poolt.

Optimeeritud Docker-piltide loomine Spring Boot rakendusele

Pilveteenuste Buildpackide eelised

Üks peamisi eeliseid Buildpacki kasutamisel piltide loomisel on see, et pildi konfiguratsiooni muudatusi saab hallata keskselt (builder) ja levitada kõikidele rakendustele, mis kasutavad builderit.

Buildpackid on olnud tihedalt seotud platvormiga. Cloud-Native Buildpackid tagavad standardiseerimise platvormide vahel, toetades OCI pildi formaati, mis garanteerib, et pilt saab töötada Docker'i mootori all.

Spring Booti plugin

Spring Booti plugin loob OCI pilte lähtekoodist Buildpacki abil. Pildid luuakse kasutades bootBuildImageülesandeid (Gradle) või spring-boot:build-imageeesmärke (Maven) ja kohalikku Docker'i installatsiooni.

Saame seadistada vajaliku pildi nime, et see saadetaks Docker'i registrisse, määrates nime 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>

Kasutame Mavenit rakenduse loomise ja konteineripildi loomise ülesande täitmiseks. build-imageeesmärgi täitmiseks. Praegu me ei kasuta mingeid Docker'i faile.

mvn spring-boot:build-image

Tulemus on ligikaudu selline:

[INFO] --- spring-boot-maven-plugin:2.3.3.RELEASE:build-image (default-cli) @ usersignup ---
[INFO] Ehitus on käimas 'docker.io/pratikdas/usersignup:v1'
[INFO] 
[INFO]  > Hakkame alla laadima ehitajapilti 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 0%
.
.
.. [looja]     Lisa sildid 'org.springframework.boot.version'
.. [looja]     *** Pildid (c311fe74ec73):
.. [looja]           docker.io/pratikdas/usersignup:v1
[INFO] 
[INFO] Kätering 'docker.io/pratikdas/usersignup:v1' on edukalt loodud

Väljundist näeme, et paketo Cloud-Native buildpackkasutatakse OCI pildi loomisel. Nagu varem, saame näha, et pilt on määratud Docker pildiks, käivitades käsu:

docker images 

Väljund:

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

Konteineripildi loomine Jibi abil

Jib on Google'i pildiloome plugin, mis pakub alternatiivset meetodit konteineripildi loomiseks lähtekoodist.

Seadistame jib-maven-pluginfailis pom.xml:

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

Seejärel käivitame Jibi plugina Maven'i käsuga, et ehitada rakendus ja luua konteineripilt. Nagu varem, ei kasuta me siin ühtegi Docker faili:

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

Pärast ülaltoodud Maven käsu täitmist saame järgmise väljundi:

[INFO] Rakenduse konteinerimine pratikdas/usersignup:v1...
.
.
[INFO] Konteineri sisenemispunkt seadistatud [java, -cp, /app/resources:/app/classes:/app/libs/*, io.pratik.users.UsersignupApplication]
[INFO] 
[INFO] Kujundatud ja üles laaditud pilt pratikdas/usersignup:v1
[INFO] Tegevuste täitmine:
[INFO] [==============================] 100.0% valminud

Väljund näitab, et konteineri pilt on loodud ja paigutatud registrisse.

Motiivid ja meetodid optimeeritud piltide loomisel

Meil on kaks peamist põhjust optimeerimiseks:

  • Tootlikkus: konteinerite orkestreerimise süsteemis tõmmatakse konteineri pilt registrist hostisse, kus konteinerimehhanism töötab. See protsess nimetatakse planeerimiseks. Suure suurusega piltide tõmbamine registrist põhjustab pikema planeerimise aega konteinerite orkestreerimise süsteemides ja pikema koostamise aega CI torudes.
  • Ohutus: suurte piltide puhul on ka suurem haavatavus.

Docker pilt koosneb kihtide kastist, millest igaüht esindab käsku meie Dockerfile'is. Iga kiht esindab alumise kihi muudatusi. Kui me tõmbame Docker'i pildi registrist, tõmmatakse see kihtide kaupa ja vahemällu hostis.

Spring Boot kasutab «paksu JAR» vaikimisi paketiformaadina. Kui vaatame paksu JAR-i, näeme, et rakendus moodustab väga väikese osa kogu JAR-ist. See on osa, mis muutub kõige sagedamini. Ülejäänud osa koosneb Spring Frameworki sõltuvustest.

Optimeerimise valem keskendub rakenduse isoleerimisele eraldi kihis Spring Frameworki sõltuvustest.

Sõltuvuste kiht, mis moodustab paksu JAR-faili põhilise osa, laaditakse ainult üks kord ja vahemällu host-süsteemis.

Ainult rakenduse õhuke kiht tõmmatakse rakenduse värskenduste ja konteinerite planeerimise ajal, kuidas on näidatud sellel diagrammil:

Optimeeritud Docker-piltide loomine Spring Boot rakendusele

Järgmistes jaotistes vaatame, kuidas luua neid optimeeritud pilte Spring Boot rakenduse jaoks.

Optimeeritud konteineripildi loomine Spring Boot rakendusele Buildpacki abil

Spring Boot 2.3 toetab kihilisust, eraldades paksu JAR-faili osad eraldi kihtidesse. Kihistamise funktsioon on vaikimisi keelatud ja see tuleb selgelt lubada Spring Boot Maven plugina abil:

org.springframework.boot
  spring-boot-maven-plugin
  
    
      true

Kasutame seda konfiguratsiooni meie konteineripildi loomiseks kõigepealt Buildpack'i ja seejärel Docker'i järgmistes jaotistes.

Käivitame build-imageMaven'i eesmärgi konteineripildi loomiseks:

mvn spring-boot:build-image

Kui käivitame Dive, et vaadata tulemuspildis kihte, näeme, et rakenduse kiht (millel on punane joon) on palju väiksem kilobaitide ulatuses võrreldes sellega, mida saime kasutades paksu JAR-formaati:

Optimeeritud Docker-piltide loomine Spring Boot rakendusele

Optimeeritud konteineripildi loomine Spring Boot rakendusele Docker'in kasutamisega

Maven'i või Gradle'i plugina kasutamise asemel saame samuti luua palju kihilise Docker JAR-faili koos Docker failiga.

Dockerit kasutades peame kahe lisaastme läbima, et kihid välja võtta ja need lõpppildisse kanda.

Pärast Maveniga kokkupanekut, kus on sisse lülitatud kihistamisfunktsioon, näeb saadud JAR välja järgmine:

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

Väljundis kuvatakse täiendav JAR nimega spring-boot-jarmode-layertoolsja layersfle.idxfail. See täiendav JAR-fail võimaldab mitmekihilist töötlemist, nagu on kirjeldatud järgmises osas.

Sõltuvuste eraldamine eraldi kihtides

Kihide vaatamiseks ja eraldamiseks meie mitmekihilisest JAR-ist kasutame süsteemi omadust -Djarmode=layertoolsrakenduse asemel JAR-i käivitamiseks: spring-boot-jarmode-layertoolsjava -Djarmode=layertools -jar target/usersignup-0.0.1-SNAPSHOT.jar

Selle käsu täitmine annab väljundi, mis sisaldab saadaval olevaid käsuvalikuid:

Kasutamine: java -Djarmode=layertools -jar usersignup-0.0.1-SNAPSHOT.jarSaadaval käsud: list Loetlege kihid jar-is, mida saab eraldada extract Eemaldab kihid jar-ist pildi loomiseks help Abi mis tahes käsu kohta

Väljund näitab käske

Väljund näitab käske loendextractja helpkoos helpolema vaikimisi. Käivitatakse käsu koos loendvalikuga:

java -Djarmode=layertools -jar target/usersignup-0.0.1-SNAPSHOT.jar list
sõltuvused
spring-boot-loader
snapshot-sõltuvused
rakendus

Näeme sõltuvuste loendit, mida saab kihtidena lisada.

Vaikimisi kihid:

Kihi nimetus

Sisu

sõltuvused

ükskõik milline sõltuvus, mille versioon ei sisalda SNAPSHOT

spring-boot-loader

JAR'i laadimise klassid

snapshot-sõltuvused

ükskõik milline sõltuvus, mille versioon sisaldab SNAPSHOT

rakendus

rakenduse klassid ja ressursid

Kihid on määratletud layers.idxfailis sellises järjekorras, milles need tuleb Docker'i kujundisse lisada. Need kihid vahemälu salvestatakse hostis pärast esimest allalaadimist, kuna need ei muutu. Hostile laaditakse ainult täiendatud rakenduse kiht, mis toimub kiiremini vähenenud suuruse tõttu. .

Kujundi koostamine sõltuvustega, eraldi kihtidena allalaaditud

Me ehitame lõpliku kujundi kahes etapis, kasutades meetodit, mida nimetatakse mitmeastmeliseks koostamiseks . Esimeses etapis allalaadime sõltuvused ja teises etapis kopeerime allalaaditud sõltuvused lõplikku kujundisse.

Modifitseerime meie Docker'i faili mitmeastmeliseks koostamiseks:

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

Salvestame selle konfiguratsiooni eraldi faili — Dockerfile2.

Koostame Docker'i kujundi järgmise käsuga:

docker build -f Dockerfile2 -t usersignup:v1 .

Pärast selle käsu täitmist saame järgmise väljundi:

Saadan ehituskonteksti Docker daemonile 20,41 MB
Samm 1/12 : FROM adoptopenjdk:14-jre-hotspot kui ehitaja
14-jre-hotspot: Laadimine raamatukogust/adoptopenjdk
.
.
Ehitamine õnnestus a9ebf6970841
Sildistamine õnnestus userssignup:v1

Näeme, et Docker-i pilt luuakse pildi ID-ga ja seejärel sildistatakse.

Lõpuks käivitame Dive käsu nagu varem, et kontrollida genereeritud Docker-pildi kihte. Saame anda ID või sildi Dive käsu sisendiks:

dive userssignup:v1

Nagu väljundist nähtub, hõivab nüüd rakendust sisaldav kiht vaid 11 KB, samas kui sõltuvused on eraldi kihtides vahemälus. 

Optimeeritud Docker-piltide loomine Spring Boot rakendusele

Sisemiste sõltuvuste hankimine eraldi kihtides

Saame veelgi vähendada rakenduse kihi suurust, tuues eraldi kihina välja kõik meie kasutaja sõltuvused, selle asemel et neid koos rakendusega pakkida, kuulutades need ymlsarnases failis nimega 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/"

Selles failis layers.idxoleme lisanud kohandatud sõltuvuse nimega, io.myorgorganisatsiooni sõltuvustest, mis on saadud ühest hoidlast.

Kokkuvõte

Selles artiklis vaatlesime Cloud-Native Buildpackide kasutamist konteineri pildi loomiseks otse allikakoodist. See on alternatiiv Dockerile, kasutades konteineri pildi loomise traditsioonilist viisi: esmalt luuakse paks JAR-fail ja seejärel pakitakse see konteineripildiks, määrates juhised Dockerfile'is.

Käsitlesime ka meie konteineri optimeerimist, lisades kihistamisfunktsiooni, mis eraldab sõltuvused eraldi kihtidesse, mis vahelduvad hostis, ja õhuke rakenduse kiht laaditakse üles, kui konteineri käitamismehhanismid plaanivad.

Kogu artiklis kasutatud allikakood on saadaval aadressil Github .

Käskude käsiraamat

Siin on lühikokkuvõte käskudest, mida kasutasime käesolevas artiklis kiiremaks tutvumiseks.

Konteksti puhastamine:

docker system prune -a

Konteineripildi loomine Dockerfile'i abil:

docker build -f  -t  .

Konteineripildi kogumine allikakoodist (ilma Dockerfile'ita):

mvn spring-boot:build-image

Sõltuvuste kihtide vaatamine. Enne rakenduse JAR-faili kogumist veenduge, et spring-boot-maven-pluginis on kihtide ülekatte funktsioon sisse lülitatud:

java -Djarmode=layertools -jar application.jar list

Sõltuvuste kihtide ekstraktsioon. Enne rakenduse JAR-faili kogumist veenduge, et spring-boot-maven-pluginis on kihtide ülekatte funktsioon sisse lülitatud:

 java -Djarmode=layertools -jar application.jar extract

Konteinerite piltide loendi vaatamine

docker images

Konteineri pildis olevate kihtide vaatamine (veenduge, et sukeldumise tööriist on installitud):

dive

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster