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. .
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 standard: 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.
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 koos sõltuvustega web, lombokja 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 packageSee 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 229MBVaadake konteineripildi kihte
Vaadakem pilti kihist, kasutades et vaadata neid kihte:
dive usersignup:v1Siin on osa Dive käsu täitmise tulemustest:

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
() — 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.

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-imageTulemus 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 loodudVä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 257MBKonteineripildi 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:v1Pä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% valminudVä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 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:

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
trueKasutame 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-imageKui 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 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.idxVä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äskeVäljund näitab käske loend, extractja helpkoos helpolema vaikimisi. Käivitatakse käsu koos loendvalikuga:
java -Djarmode=layertools -jar target/usersignup-0.0.1-SNAPSHOT.jar listsõltuvused
spring-boot-loader
snapshot-sõltuvused
rakendusNä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 . 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:v1Nä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:v1Nagu väljundist nähtub, hõivab nüüd rakendust sisaldav kiht vaid 11 KB, samas kui sõltuvused on eraldi kihtides vahemälus.

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 .
Käskude käsiraamat
Siin on lühikokkuvõte käskudest, mida kasutasime käesolevas artiklis kiiremaks tutvumiseks.
Konteksti puhastamine:
docker system prune -aKonteineripildi loomine Dockerfile'i abil:
docker build -f -t .Konteineripildi kogumine allikakoodist (ilma Dockerfile'ita):
mvn spring-boot:build-imageSõ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 listSõ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 extractKonteinerite piltide loendi vaatamine
docker imagesKonteineri pildis olevate kihtide vaatamine (veenduge, et sukeldumise tööriist on installitud):
diveAllikas: habr.com
