Optimeeritud Dockeri piltide loomine kevadise käivitamise rakenduse jaoks

Konteinerid on muutunud eelistatud vahendiks rakenduse pakendamiseks koos kõigi selle tarkvara- ja operatsioonisüsteemisõltuvustega ning seejärel erinevatesse keskkondadesse toimetamiseks.

See artikkel hõlmab erinevaid võimalusi Spring Booti rakenduse konteinerisse paigutamiseks:

  • Dockeri kujutise loomine dockeri faili abil,
  • OCI-pildi loomine allikast Cloud-Native Buildpacki abil,
  • ja pildi optimeerimine käitusajal, eraldades JAR-i osad erinevateks tasemeteks, kasutades kihilisi tööriistu.

 Koodi näide

Selle artikliga on kaasas töötav koodinäide GitHubis .

Konteinerite terminoloogia

Alustame kogu artiklis kasutatud konteinerterminoloogiaga:

  • Konteineri pilt: kindlas vormingus fail. Teisendame oma rakenduse konteinerpildiks, käivitades ehitustööriista.
  • Konteiner: konteineri kujutise käivitatav eksemplar.
  • Konteineri mootor: konteineri käitamise eest vastutav deemonprotsess.
  • Konteineri host: hostmasin, millel konteineri mootor töötab.
  • Konteinerite register: konteineri kujutise avaldamiseks ja levitamiseks kasutatav üldine asukoht.
  • OCI standardAvatud konteinerite algatus (OCI) on kerge avatud lähtekoodiga haldusraamistik, mille on moodustanud Linux Foundation. OCI kujutise spetsifikatsioon määratleb konteineri kujutise vormingute ja käitusaja standardid, et kõik konteinerimootorid saaksid käitada mis tahes ehitustööriistaga loodud konteineri kujutisi.

Rakenduse konteinerisse paigutamiseks mähime oma rakenduse konteineri kujutisse ja avaldame selle pildi avalikus registris. Konteineri käitusaeg hangib selle pildi registrist, pakib selle lahti ja käivitab selle sees oleva rakenduse.

Spring Booti versioon 2.3 pakub pistikprogramme OCI-piltide loomiseks.

laevalaadija on kõige sagedamini kasutatav konteineri rakendus ja me kasutame oma näidetes Dockerit, nii et kõik järgnevad konteineri viited selles artiklis viitavad Dockerile.

Konteinerpildi loomine traditsioonilisel viisil

Dockeri piltide loomine Spring Booti rakenduste jaoks on väga lihtne, lisades oma Dockerfile'i mõned juhised.

Esmalt loome käivitatava JAR-i ja osana Dockerfile'i juhistest kopeerime käivitatava JAR-i pärast vajalike kohanduste rakendamist JRE põhipildi peale.

Loome oma kevadise rakenduse Kevadine algseade sõltuvustega weblombokи actuator. Lisame API pakkumiseks ka puhkekontrolleri GETmeetod.

Dockeri faili loomine

Seejärel asetame selle rakenduse lisamise teel konteinerisse Dockerfile:

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

Meie Dockerfile sisaldab põhipilti, alates adoptopenjdk, mille peale kopeerime oma JAR-faili ja avame seejärel pordi, 8080mis kuulab taotlusi.

Rakenduse kokkupanek

Kõigepealt peate looma rakenduse Maven või Gradle abil. Siin kasutame Mavenit:

mvn clean package

See loob rakenduse jaoks käivitatava JAR-faili. Dockeri mootoris töötamiseks peame selle käivitatava JAR-i teisendama Dockeri pildiks.

Loo konteineri pilt

Seejärel paneme selle JAR-i käivitatava faili Dockeri pildile, käivitades käsu docker buildvarem loodud Dockerfile'i sisaldava projekti juurkataloogist:

docker build  -t usersignup:v1 .

Näeme oma pilti loendis käsuga:

docker images 

Ülaltoodud käsu väljund sisaldab meie pilti usersignupkoos põhipildiga, adoptopenjdktäpsustatud meie Dockerfile'is.

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

Vaadake konteineri kujutise sees olevaid kihte

Vaatame pildi sees olevat kihtide virna. Me kasutame tööriist  sukelduma, nende kihtide vaatamiseks:

dive usersignup:v1

Siin on osa sukeldumiskäsu väljundist: 

Optimeeritud Dockeri piltide loomine kevadise käivitamise rakenduse jaoks

Nagu näeme, moodustab rakenduse kiht olulise osa pildi suurusest. Soovime optimeerimise osana järgmistes jaotistes selle kihi suurust vähendada.

Konteineri kujutise loomine Buildpacki abil

Komplekteerimispaketid (Ehituspakid) on üldtermin, mida kasutavad erinevad platvormi teenusena (PAAS) pakkumised lähtekoodist konteineri kujutise loomiseks. Selle käivitas Heroku 2011. aastal ja sellest ajast alates on selle kasutusele võtnud Cloud Foundry, Google App Engine, Gitlab, Knative ja mõned teised.

Optimeeritud Dockeri piltide loomine kevadise käivitamise rakenduse jaoks

Cloud Build pakettide eelis

Kujutiste koostamiseks Buildpacki kasutamise üks peamisi eeliseid on see pildi konfiguratsiooni muudatusi saab hallata tsentraalselt (ehitaja) ja levitada kõikidesse ehitajat kasutavatesse rakendustesse.

Ehituspaketid olid platvormiga tihedalt seotud. Cloud-Native Buildpackid pakuvad platvormide standardimist, toetades OCI pildivormingut, mis tagab, et pilti saab käitada Dockeri mootor.

Spring Boot Plugina kasutamine

Spring Booti pistikprogramm loob OCI-kujutisi allikast, kasutades Buildpacki. Pildid luuakse kasutades bootBuildImageülesanded (Gradle) või spring-boot:build-imagesihtmärk (Maven) ja kohalik Dockeri installimine.

Saame kohandada pildi nime, mida peame Dockeri registrisse lükkama, 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 täitmiseks Mavenit build-imagerakenduse loomise ja konteineri kujutise loomise eesmärgid. Me ei kasuta praegu ühtegi Docker-faili.

mvn spring-boot:build-image

Tulemus saab olema umbes selline:

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

Väljundist näeme seda paketo Cloud-Native buildpackkasutatakse töötava OCI-pildi loomiseks. Nagu varemgi, näeme pilti Dockeri kujutisena, käivitades käsu:

docker images 

Järeldus:

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

Konteineri pildi loomine Jibiga

Jib on Google'i piltide loomise pistikprogramm, mis pakub alternatiivset meetodit konteineri kujutise loomiseks allikast.

Konfigureerimine jib-maven-pluginpom.xml-s:

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

Järgmisena käivitame rakenduse koostamiseks ja konteineri kujutise loomiseks käsu Maven abil pistikprogrammi Jib. Nagu varemgi, 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] 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

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

Motivatsioonid ja meetodid optimeeritud piltide loomiseks

Meil on optimeerimiseks kaks peamist põhjust:

  • Производительность: konteineri orkestreerimissüsteemis tõmmatakse konteineri kujutis pildiregistrist konteinerimootorit käitavasse hosti. Seda protsessi nimetatakse planeerimiseks. Suurte kujutiste tõmbamine registrist toob kaasa pikad ajastamisajad konteinerite orkestreerimissüsteemides ja pikad ehitusajad CI torujuhtmetes.
  • turvalisus: suurtel piltidel on ka suur ala turvaaukude jaoks.

Dockeri pilt koosneb kihtide virnast, millest igaüks esindab avaldust meie Dockerfile'is. Iga kiht tähistab aluskihi muutuste deltat. Kui tõmbame registrist Dockeri pildi, tõmmatakse see kihtidena ja salvestatakse hosti vahemällu.

Spring Boot kasutab "paks JAR" sisse vaikepakendivorminguna. Kui vaatame paksu JAR-i, näeme, et rakendus on väga väike osa kogu JAR-ist. See on osa, mis muutub kõige rohkem. Ülejäänud osa koosneb Spring Frameworki sõltuvustest.

Optimeerimisvalem keskendub rakenduse eraldamisele Spring Frameworki sõltuvustest eraldi tasemel.

Sõltuvuskiht, mis moodustab suurema osa paksust JAR-failist, laaditakse alla ainult üks kord ja salvestatakse hostsüsteemi vahemällu.

Rakenduse värskendamise ja konteineri ajastamise ajal tõmmatakse rakendusest ainult õhuke kiht, nagu on näidatud sellel diagrammil:

Optimeeritud Dockeri piltide loomine kevadise käivitamise rakenduse jaoks

Järgmistes jaotistes vaatleme, kuidas neid optimeeritud pilte Spring Booti rakenduse jaoks luua.

Kevadkäivitusrakenduse jaoks optimeeritud konteinerpildi loomine koos Buildpackiga

Spring Boot 2.3 toetab kihistamist, eraldades paksu JAR-faili osad eraldi kihtideks. Kihistamise funktsioon on vaikimisi keelatud ja see tuleb Spring Boot Maven pistikprogrammi abil selgesõnaliselt lubada:

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

Kasutame seda konfiguratsiooni oma konteineri kujutise koostamiseks esmalt Buildpacki ja seejärel järgmistes jaotistes Dockeriga.

Jookseme build-imageMaven sihtmärk konteineri kujutise loomiseks:

mvn spring-boot:build-image

Kui käivitame Dive'i, et näha saadud pildil olevaid kihte, näeme, et rakendusekiht (punase ringiga) on kilobaidivahemikus palju väiksem kui paksu JAR-vorminguga.

Optimeeritud Dockeri piltide loomine kevadise käivitamise rakenduse jaoks

Dockeriga kevadkäivitusrakenduse jaoks optimeeritud konteinerpildi loomine

Maveni või Gradle'i pistikprogrammi asemel saame luua ka Dockeri failiga kihilise Dockeri JAR-kujutise.

Dockeri kasutamisel peame kihtide eraldamiseks ja lõplikule pildile kopeerimiseks tegema kaks lisatoimingut.

Saadud JAR-i sisu näeb pärast Maveni ehitamist koos lubatud kihilisusega 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äljund näitab täiendavat JAR-i nimega spring-boot-jarmode-layertoolsи layersfle.idxfaili. See täiendav JAR-fail pakub kihistamise võimalusi, nagu on kirjeldatud järgmises jaotises.

Eraldi kihtide sõltuvuste eraldamine

Meie kihilise JAR-i kihtide vaatamiseks ja ekstraktimiseks kasutame süsteemi atribuuti -Djarmode=layertoolsalustuseks spring-boot-jarmode-layertoolsJAR rakenduse asemel:

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

Selle käsu käivitamine annab väljundi, mis sisaldab saadaolevaid käsuvalikuid:

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

Väljund näitab käske listextractи helpс helpolla vaikeseade. Käivitame käsuga listvalik:

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

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

Vaikimisi kihid:

Kihi nimi

Sisu

dependencies

mis tahes sõltuvus, mille versioon ei sisalda SNAPSHOTI

spring-boot-loader

JAR-laaduri klassid

snapshot-dependencies

mis tahes sõltuvus, mille versioon sisaldab SNAPSHOTI

application

rakendusklassid ja ressursid

Kihid on määratletud layers.idxfaili selles järjekorras, milles need tuleks Dockeri pildile lisada. Need kihid salvestatakse hosti vahemällu pärast esimest toomist, kuna need ei muutu. Hostisse laaditakse alla ainult värskendatud rakendusekiht, mis on vähendatud suuruse tõttu kiirem .

Kujutise loomine, mille sõltuvused on eraldatud eraldi kihtidesse

Ehitame lõpliku pildi kahes etapis, kasutades meetodit nimega mitmeastmeline kokkupanek . Esimeses etapis eraldame sõltuvused ja teises etapis kopeerime eraldatud sõltuvused lõppu.

Muutkem oma Docker-faili mitmeetapilise 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.

Ehitame Dockeri pildi käsuga:

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 Dockeri pilt luuakse pildi ID-ga ja seejärel märgistatakse.

Lõpuks käivitame käsu Sukeldumine nagu varem, et kontrollida loodud Dockeri pildi sees olevaid kihte. Sukeldumiskäsule saame sisestada pildi ID või sildi:

dive userssignup:v1

Nagu väljundist näha, on rakendust sisaldav kiht nüüd vaid 11 KB ja sõltuvused on vahemällu salvestatud eraldi kihtidena. 

Optimeeritud Dockeri piltide loomine kevadise käivitamise rakenduse jaoks

Eraldi kihtidest eraldage sisemised sõltuvused

Rakenduskihi suurust saame veelgi vähendada, eraldades kõik oma kohandatud sõltuvused eraldi kihiks, selle asemel, et pakkida need koos rakendusega, deklareerides need ymlsarnase faili 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.myorgmis sisaldab jagatud hoidlast alla laaditud organisatsiooni sõltuvusi.

Väljund

Selles artiklis vaatlesime Cloud-Native Buildpacksi kasutamist konteineri kujutise loomiseks otse allikast. See on alternatiiv Dockeri kasutamisele konteineri kujutise loomiseks tavapärasel viisil: esmalt luuakse paks käivitatav JAR-fail ja seejärel pakitakse see konteineri kujutiseks, täpsustades Dockerfile'is olevaid juhiseid.

Samuti uurisime oma konteineri optimeerimist, lisades kihistamisfunktsiooni, mis eraldab sõltuvused eraldi kihtideks, mis salvestatakse hosti vahemällu, ja õhuke rakenduskiht laaditakse ajastamisajal konteineri täitmismootoritesse.

Kogu artiklis kasutatud lähtekoodi leiate aadressilt Github .

Käskude viide

Siin on kiire ülevaate saamiseks selles artiklis kasutatud käskude kokkuvõte.

Konteksti tühjendamine:

docker system prune -a

Konteineri kujutise loomine Dockerfile'iga:

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

Ehitage konteineri kujutis allikast (ilma Dockerfile'ita):

mvn spring-boot:build-image

Vaata sõltuvuskihte. Enne rakenduse jar-faili loomist veenduge, et kihistamise funktsioon oleks pluginas spring-boot-maven-plugin lubatud:

java -Djarmode=layertools -jar application.jar list

Sõltuvuskihtide eraldamine. Enne rakenduse jar-faili loomist veenduge, et kihistamise funktsioon oleks pluginas spring-boot-maven-plugin lubatud:

 java -Djarmode=layertools -jar application.jar extract

Konteinerite piltide loendi vaatamine

docker images

Vaade konteineri kujutise sees vasakul (veenduge, et sukeldumistööriist on installitud):

dive <image ID or image tag>

Allikas: www.habr.com