Optimeeritud Docker-piltide loomine Spring Boot rakendusele

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 GitHubis .

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 standardOpen Container Initiative (OCI) 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.

Docker - 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 Spring Initializr sõltuvustega weblombokja 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 package

See 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      229MB

Konteineripildi kihtide vaatamine

Vaatame pilti kihtide virna. Kasutame vahend  dive, et vaadata neid kihte:

dive usersignup:v1

Siin on osa Dive käsu tulemustest: 

Optimeeritud Docker-piltide loomine Spring Boot rakendusele

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

Kogumispaketid (Buildpacks) 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.

Optimeeritud Docker-piltide loomine Spring Boot rakendusele

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-image

Tulemus 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                  257MB

Konteineripildi 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:v1

Pä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äidetud

Vä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 "paksu JAR'i" vaikimisi pakendamisformaadina. Kui vaatame paksu JAR'i, näeme, et rakendus moodustab väga väikese osa kogu JAR-st. See on osa, mis muutub kõige sagedamini. Ülejäänud osa koosneb Spring Framework'i sõltuvustest. 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 Docker-piltide loomine Spring Boot rakendusele

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
  
    
      true

Kasutame 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-image

Kui 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 Docker-piltide loomine Spring Boot rakendusele

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.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 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äsklused

extract loendolema 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
application
Nä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 mitmeastmeliseks ehitamiseks . 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:v1

Nä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:v1

Väljundi põhjal on rakendust sisaldav kiht nüüd vaid 11 KB ja sõltuvused vahelduvad eraldi kihtides. 

Optimeeritud Docker-piltide loomine Spring Boot rakendusele

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 Github .

Käskude juhend

Siin on kokkuvõte käskudest, mida kasutasime selles artiklis kiireks tutvumiseks.

Konteksti puhastamine:

docker system prune -a

Konteineripildi loomine Dockerifaili abil:

docker build -f  -t  .

Konteineripildi koostamine lähtekoodist (ilma Dockerifailita):

mvn spring-boot:build-image

Sõltuvuste kihtide vaatamine. Enne rakenduse JAR-faili koostamist veenduge, et kihistamise funktsioon on lubatud spring-boot-maven-pluginis:

java -Djarmode=layertools -jar application.jar list

Sõ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 extract

Konteineripiltide loendi vaatamine

docker images

Konteineripildi sees olevate kihtide vaatamine (veenduge, et teil on installitud sukeldumise tööriist):

dive

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster