Konteinerid on saanud eelistatud viisiks aplikatsioonide pakendamiseks koos kõikide tarkvara ja operatsioonisüsteemi sõltuvustega ning nende edastamiseks erinevatesse keskkondadesse.
Selles artiklis käsitletakse erinevaid Spring Boot rakenduse konteineriseerimise viise:
- Docker pildi loomine Docker faili abil,
- OCI pildi loomine lähtekoodist Cloud-Native Buildpacki abil,
- ja pildi optimeerimine käitamise ajal JAR osade jagamise kaudu erinevatele tasemetele mitme taseme tööriistade abil.
Koodinäide
See artikkel sisaldab töötava koodi näidet .
Konteinerite terminoloogia
Alustame artiklis kasutatavast konteinerite terminoloogiast:
- Konteineri pilt (Container image): teatud formaadifail. Me konverteerime meie rakenduse konteineripildiks, käivitades ehitusriista.
- Konteiner: konteineripildi täidise eksemplar.
- Konteineri mootor (Container engine): demon-protsess, mis vastutab konteineri käitamise eest.
- Konteineri host (Container host): host-arvuti, millel konteineri mootor töötab.
- Konteinerite register (Container registry): ühine asukoht, mida kasutatakse konteineripildi avaldamiseks ja levitamiseks.
- OCI standard: on kerge avatud haldusraamistik, mis on loodud Linux Foundationi raames. OCI pildispetsiifikatsioon määratleb tööstuse standardid konteineripiltide ja käituskeskkondade formaatide jaoks, et tagada, et kõik konteinerimootorid suudavad käitada konteineripilte, mis on loodud mistahes ehitusriista abil.
Rakenduse konteinerisse panemiseks koostame meie rakenduse konteineripildiks ja avaldame selle pildi ühises registris. Konteineri käituskeskkond tõmbab selle pildi registrist, dekompileerib selle ja käivitab rakenduse selle sees.
Spring Boot versioon 2.3 pakub pluginaid OCI piltide loomiseks.
- kõige laialdasemalt kasutatav konteinerite teostus, ja meie näidetes kasutame Dockerit, seega kõik järgmised viidatud konteinerid selles artiklis tähendavad Dockerit.
Konteineripildi loomine traditsioonilisel viisil
Docker piltide loomine Spring Boot rakenduste jaoks on väga lihtne, lisades paar juhist Docker failile.
Esiteks loome JAR-faili ja Docker-faili juhistes kopeerime JAR-faili JRE põhifaili peale, pärast vajalike seadete rakendamist.
Lähme looma meie Springi rakendust sõltuvustega web, lombokja actuator. Me lisame ka rest-kontrolleri, et pakkuda API-d GETmeetodiga.
Docker-faili loomine
Seejärel paneme 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 põhifaili, mille peal adoptopenjdk, kuhu kopeerime oma JAR-faili ja seejärel avame pordi, 8080mis kuulab päringutele.
Rakenduse koostamine
Esiteks tuleb rakendus luua Maveniga või Gradlega. Siin kasutame Mavenit:
mvn clean packageSee loob rakenduse käivitatava JAR-faili. Peame selle käivitatava JAR-i muutma Docker-pildiks, et see töötaks Dockerite ekosüsteemis.
Konteineri pildi loomine
Seejärel paneme selle käivitatava JAR-faili Docker-pilti, käivitades käsu docker buildprojekti juurkataloogist, mis sisaldab varem loodud Docker-faili:
docker build -t usersignup:v1 .Saame oma pildi loendi vaatamiseks kasutada käsku:
docker images Ülaltoodud käsu tulemus näitab meie pilti usersignupkoos põhifiltriga, adoptopenjdk, mis on meie Docker-failis määratud.
REPOSITORY TAG SIZE
usersignup v1 249MB
adoptopenjdk 11-jre-hotspot 229MBKonteineripildi kihtide vaatamine
Vaatame pilti kihtide virna. Kasutame et vaadata neid kihte:
dive usersignup:v1Siin on osa Dive käsu tulemustest:

Kuidas me näeme, et rakenduskiht võtab suure osa pildi suurusest. Soovime selle kihi suurust järgnevates jaotistes optimeerimise raames vähendada.
Konteineri pildi loomine Buildpacki abil
() on üldine mõisted, mida kasutavad erinevad „Platvorm kui teenus” (PAAS) pakkumised konteineripildi loomiseks lähtekoodist. See käivitati Heroku poolt 2011. aastal ja on selle ajaga vastu võetud Cloud Foundry, Google App Engine, Gitlab, Knative ja mõne muu poolt.

Pilve Buildpackide eelis
Üks peamisi eeliseid Buildpackide kasutamisel piltide loomiseks on see, et Kujunduse muutustega saab keskselt hallata (builder) ja jaotada kõikidele rakendustele, mis kasutavad builderit.
Kogumispaketid olid tihedalt seotud platvormiga. Cloud-Native Buildpacks tagavad standardimise platvormide vahel, toetades OCI pildiformaati, mis garanteerib, et pilti saab käitada Docker'i mootori abil.
Spring Boot plugina kasutamine
Spring Boot plugin loob OCI pilte allikakoodist, kasutades Buildpack'i. Pildid luuakse kasutades bootBuildImageülesandeid (Gradle) või spring-boot:build-imageeesmärke (Maven) ja kohalikku Docker'i installatsiooni.
Saame konfigureerida pildi nime, mis on vajalik Docker registrisse saatmiseks, 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, et täita build-imageeesmärk, et luua rakendus ja konteineripilt. Praegu me ei kasuta mingeid Docker'i faile.
mvn spring-boot:build-imageTulemus on umbes järgmine:
[INFO] --- spring-boot-maven-plugin:2.3.3.RELEASE:build-image (default-cli) @ usersignup ---
[INFO] Ehitatakse pilti 'docker.io\/pratikdas\/usersignup:v1'
[INFO]
[INFO] > Tõmmates builderi pilti 'gcr.io\/paketo-buildpacks\/builder:base-platform-api-0.3' 0%
.
.
.. [creator] Lisatakse silt 'org.springframework.boot.version'
.. [creator] *** Pildid (c311fe74ec73):
.. [creator] docker.io\/pratikdas\/usersignup:v1
[INFO]
[INFO] Pilti 'docker.io\/pratikdas\/usersignup:v1' ehitati edukalt.Väljundist näeme, et paketo Cloud-Native buildpackkasutatakse töötava OCI pildi loomiseks. Nagu enne, saame pildi näha Docker pildina, käivitades käsu:
docker images Kokkuvõte:
REPOSITORY SIZE
paketobuildpacks\/run 84.3MB
gcr.io\/paketo-buildpacks\/builder 652MB
pratikdas\/usersignup 257MBKonteineripildi loomine Jibi abil
Jib on Google'i piltide loomise plugin, mis pakub alternatiivset meetodit konteineripildi loomiseks allikakoodist.
Seame üles 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äsu abil, et ehitada rakendus ja luua konteineripilt. Nagu enne, me ei kasuta mingeid Docker'i faile:
mvn compile jib:build -Dimage=<docker registry name>\/usersignup:v1Pärast ülaltoodud Maven'i 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] Pilt on ehitatud ja tõugatud: pratikdas/usersignup:v1
[INFO] Tegevuste täitmine:
[INFO] [==============================] 100.0% täidetudVäljund näitab, et konteineri pilt on loodud ja salvestatud registrisse.
Motiivid ja meetodid optimeeritud piltide loomisel
Meil on kaks peamist põhjust optimeerimiseks:
- Tõhusus: konteinerite orkestreerimise süsteemis tõmmatakse konteineri pilt registrist hostisse, kus konteinerimehhanism töötab. Seda protsessi nimetatakse planeerimiseks. Suurte piltide tõmbamine registrist toob kaasa pika planeerimise aja konteinerite orkestreerimise süsteemides ja pika ehitusaega CI torudes.
- Turvalisus: suured pildid omavad ka suuremat rünnaku pindala.
Docker'i pilt koosneb kihtide reost, millest igaüks esindab käsku meie Dockerfile'is. Iga kiht esindab allpool oleva kihi muudatuste delta. Kui me tõmbame Docker'i pilti registrist, tõmmatakse see kihtidena ja kehtestatakse hostis.
Spring Boot kasutab Optimeerimise valem keskendub rakenduse isoleerimisele eraldi kihis Spring Framework'i sõltuvustest.
Sõltuvuste kiht, mis moodustab paksu JAR-faili peamise osa, laaditakse ainult üks kord ja kehtestatakse host-süsteemis.
Ainult rakenduse õhuke kiht tõmmatakse rakenduse uuendamisel ja konteinerite planeerimisel,
nagu on näidatud selles diagrammis: Järgmistes osades vaatleme, kuidas luua neid optimeeritud pilte Spring Boot rakenduse jaoks.

Optimeeritud konteineri pildi loomine Spring Boot rakendusele Buildpack'i abil
Spring Boot 2.3 toetab mitmekihilisust, tõmmates paksu JAR-faili osad eraldi kihtidena. Vaikimisi on kihistamine välja lülitatud ja see on vajalik selgesõnaliselt lubada Spring Boot Maven'i plugina abil:
Spring Boot 2.3 поддерживает многоуровневость путем извлечения частей толстого JAR-файла в отдельные слои. Функция наслоения по умолчанию отключена, и ее необходимо явно включить с помощью плагина Spring Boot Maven:
org.springframework.boot
spring-boot-maven-plugin
trueKasutame seda konfiguratsiooni meie konteineripildi loomiseks esmalt Buildpacki abil ja seejärel Dockeriga järgnevates jaotistes.
Käivitame build-imageMaveni eesmärgi konteineripildi loomiseks:
mvn spring-boot:build-imageKui käivitame Dive'i, et näha tulemuspildis kihte, näeme, et rakenduse kiht (märkitud punasega) on palju väiksem, ulatudes kilobaitideni, võrreldes sellega, mis meil oli, kasutades paksu JAR formaati:

Optimeeritud konteineripildi loomine Spring Booti rakenduse jaoks Dockeriga
Juhul, kui me ei kasuta Maveni ega Gradle'i pluginat, saame luua ka mitmekihilise JAR Dockeripildi Dockerifaili abil.
Kui kasutame Dockerit, peame tegemiseks kahe täiendava sammu, et kihte eraldada ja need lõplikku pilti kopeerida.
Maveni abil ehitatud JAR-i sisu, kus on sisse lülitatud kihistumise funktsioon, näeb välja järgnev:
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 jaotises.
Sõltuvuste eraldamine eraldi kihtidesse
Kihte meie mitmekihilisest JAR-ist vaatamiseks ja eraldamiseks kasutame süsteemi omadust -Djarmode=layertoolsrakenduse asemel JAR-i käitamiseks: 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äsklusi:Kasutus: java -Djarmode=layertools -jar usersignup-0.0.1-SNAPSHOT.jarSaadaval käsud: list Loetleb kihid jar-ist, mida saab eraldada extract Eristab kihte jar-ist pildi loomise eesmärgil help Abi iga käsu kohta
Väljal on näha käsklusedextract loend, olema vaikimisi. Käitame käsku koosja helpjot helpvalikuga: loendjava -Djarmode=layertools -jar target/usersignup-0.0.1-SNAPSHOT.jar list
dependencies
spring-boot-loader
snapshot-dependencies
applicationNäeme loetelu sõltuvustest, mida saab lisada kihtidena.Vaikimisi kihid:
Kihi nimi
igal sõltuvusel, mille versioon ei sisalda SNAPSHOT-i
Sisukord
sõltuvused
spring-boot-loader
JAR-i laadijate klassid
snapshot-dependencies
igal sõltuvusel, mille versioon sisaldab SNAPSHOT-i
rakendus
rakenduse klassid ja ressursid
классы приложений и ресурсы
Kihid on määratletud layers.idxfailis järjekorras, milles neid tuleks Docker-pildi lisamiseks kasutada. Need kihid vahelduvad hostis pärast esmakordset allalaadimist, kuna need ei muutu. Hostile laaditakse ainult rakenduse uuendatud kiht, mis toimub kiiremini väiksema suuruse tõttu. .
Pildi koostamine sõltuvustest, mis on allalaaditud eraldi kihtidena.
Loome lõpliku pildi kahes etapis, kasutades meetodit, mida nimetatakse . Esimeses etapis lahti võtame sõltuvused ja teises etapis kopeerime lahti võetud sõltuvused lõplikku pilti.
Muutame meie Docker faili mitmeastmelise ehituse jaoks:
# 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.
Kogume Docker pilti käsu abil:
docker build -f Dockerfile2 -t usersignup:v1 .Pärast selle käsu täitmist saame järgmise väljundi:
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:v1Näeme, et Docker pilt luuakse pildi ID-ga ja seejärel märgistatakse.
Lõpuks käivitame Dive käsu, nagu eelnevalt, et kontrollida kihte genereeritud Docker pildi sees. Saame määrata pildi ID või etiketi Dive käsu sisendiks:
dive userssignup:v1Väljundi põhjal on rakendust sisaldav kiht nüüd vaid 11 KB ja sõltuvused vahelduvad eraldi kihtides.

Sisemiste sõltuvuste allalaadimine eraldi kihtidena
Saame edasise rakenduse kihi suuruse vähendamiseks lahti võtta kõik meie kasutajate sõltuvused eraldi kihina, selle asemel et neid koos rakendusega pakkida, deklareerides 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 kohandatava sõltuvuse nimega, io.myorgmis sisaldab organisatsiooni sõltuvusi, saadud üldisest hoidlast.
Kokkuvõte
Selles artiklis käsitleme Cloud-Native Buildpackide kasutamist konteineripildi loomisel otse lähtekoodist. See on alternatiiv Dockerile, kus konteineripilt luuakse tavapärasel viisil: esmalt luuakse paks JAR-fail ja seejärel pakitakse see konteineripildiks, andes juhised Dockerifailis.
Käsitlesime ka meie konteineri optimeerimist, hõlmates kihistamisfunktsiooni, mis eraldab sõltuvused eraldi kihtidesse, mida vahemälus hoitakse, ja rakenduse õhuke kiht laaditakse üles konteinerite täitmise mehhanismide kavandamise ajal.
Kogu artiklis kasutatud lähtekood on saadaval .
Käskude juhend
Siin on kokkuvõte käskudest, mida kasutasime selles artiklis kiireks tutvumiseks.
Konteksti puhastamine:
docker system prune -aKonteineripildi loomine Dockerifaili abil:
docker build -f -t .Konteineripildi koostamine lähtekoodist (ilma Dockerifailita):
mvn spring-boot:build-imageSõltuvuste kihtide vaatamine. Enne rakenduse JAR-faili koostamist veenduge, et kihistamise funktsioon on lubatud spring-boot-maven-pluginis:
java -Djarmode=layertools -jar application.jar listSõltuvuste kihtide väljavõtmine. Enne rakenduse JAR-faili koostamist veenduge, et kihistamise funktsioon on lubatud spring-boot-maven-pluginis:
java -Djarmode=layertools -jar application.jar extractKonteineripiltide loendi vaatamine
docker imagesKonteineripildi sees olevate kihtide vaatamine (veenduge, et teil on installitud sukeldumise tööriist):
diveAllikas: habr.com
