Konstruado de Optimumigitaj Docker-bildoj por Spring Boot-Apliko
Ujoj fariĝis la preferata rimedo por enpaki aplikaĵon kun ĉiuj ĝiaj softvaraj kaj operaciumaj dependecoj kaj poste liveri ilin al malsamaj medioj.
Ĉi tiu artikolo kovras malsamajn manierojn enhavigi Spring Boot-aplikaĵon:
konstruante docker-bildon uzante dockerfile,
konstrui OCI-bildon el fonto uzante Cloud-Native Buildpack,
kaj bildoptimumigo ĉe rultempo disigante JAR-partojn en malsamajn nivelojn uzante tavoligitajn ilojn.
Ekzemplo de kodo
Ĉi tiu artikolo estas akompanata de funkcia kodekzemplo sur GitHub .
Uja terminologio
Ni komencos per la uja terminologio uzata tra la artikolo:
Bildo de ujo: dosiero de specifa formato. Ni konvertas nian aplikaĵon en ujan bildon rulante la konstruilon.
Ujo: plenumebla okazo de la ujo-bildo.
Kontenera motoro: La demona procezo respondeca pri rulado de la ujo.
Uja gastiganto: La gastiga maŝino sur kiu funkcias la ujo-motoro.
Registro de ujoj: La ĝenerala loko uzata por publikigi kaj distribui la ujbildon.
OCI-normo: Open Container Initiative (OCI) estas malpeza, malfermfonta administradkadro formita de la Linukso-Fondaĵo. La OCI Bilda Specifo difinas industriajn normojn por ujbildaj formatoj kaj la rultempo por certigi, ke ĉiuj ujmotoroj povas ruli ujajn bildojn kreitajn per iu ajn konstruilo.
Por kontenigi aplikaĵon, ni envolvas nian aplikaĵon en kontenerbildon kaj publikigas tiun bildon al la publika registro. La ujo rultempo prenas ĉi tiun bildon el la registro, malpakigas ĝin kaj rulas la aplikaĵon ene de ĝi.
Versio 2.3 de Spring Boot disponigas kromaĵojn por konstrui OCI-bildojn.
Docker estas la plej ofte uzata uja efektivigo, kaj ni uzas Docker en niaj ekzemploj, do ĉiuj postaj ujreferencoj en ĉi tiu artikolo referencos al Docker.
Konstrui ujan bildon laŭ la tradicia maniero
Konstrui Docker-bildojn por Spring Boot-aplikoj estas tre facila aldonante kelkajn instrukciojn al via Dockerfile.
Ni unue kreas plenumeblan JAR kaj, kiel parto de la instrukcioj de Dockerfile, kopias la plenumeblan JAR supre de la baza JRE-bildo post apliki la necesajn personigojn.
Ni kreu nian Spring-aplikaĵon Printempa Inicializr kun dependecoj web, lombokи actuator. Ni ankaŭ aldonas ripozregilon por provizi API GETmetodo.
Kreante Dockerfile
Ni tiam metas ĉi tiun aplikon en ujo per aldonado Dockerfile:
Nia Dockerfile enhavas bazan bildon, de adoptopenjdk, sur kiu ni kopias nian JAR-dosieron kaj poste malfermas la havenon, 8080kiu aŭskultos petojn.
Aplika asembleo
Unue vi devas krei aplikaĵon per Maven aŭ Gradle. Jen ni uzas Maven:
mvn clean package
Ĉi tio kreas plenumeblan JAR-dosieron por la aplikaĵo. Ni devas konverti ĉi tiun ruleblan JAR al Docker-bildo por funkcii per la Docker-motoro.
Kreu ujan bildon
Ni tiam metas ĉi tiun JAR-plenigeblan en la bildon de Docker rulante la komandon docker buildde la radika dosierujo de la projekto enhavanta la Dockerfile kreitan pli frue:
docker build -t usersignup:v1 .
Ni povas vidi nian bildon en la listo kun la komando:
docker images
La eligo de la supra komando inkluzivas nian bildon usersignupkune kun la baza bildo, adoptopenjdkspecifita en nia Dockerfile.
REPOSITORY TAG SIZE
usersignup v1 249MB
adoptopenjdk 11-jre-hotspot 229MB
Rigardu tavolojn ene de uja bildo
Ni rigardu la stakon de tavoloj ene de la bildo. Ni uzos ilo plonĝi, por vidi ĉi tiujn tavolojn:
dive usersignup:v1
Jen parto de la eligo de la Dive-komando:
Kiel ni povas vidi, la aplika tavolo konsistigas signifan parton de la bilda grandeco. Ni volas redukti la grandecon de ĉi tiu tavolo en la sekvaj sekcioj kiel parto de nia optimumigo.
Konstrui ujan bildon per Buildpack
Asembleaj pakoj (Konstrupakoj) estas ĝenerala termino uzata de diversaj proponoj de Platform as a Service (PAAS) por krei ujobildon el fontkodo. Ĝi estis lanĉita de Heroku en 2011 kaj poste estis adoptita de Cloud Foundry, Google App Engine, Gitlab, Knative kaj kelkaj aliaj.
Avantaĝo de Cloud Build Packages
Unu el la ĉefaj avantaĝoj uzi Buildpack por konstrui bildojn estas tio bildaj agordaj ŝanĝoj povas esti administritaj centre (konstruanto) kaj disvastigitaj al ĉiuj aplikoj uzante la konstruilon.
La konstrupakaĵoj estis proksime ligitaj al la platformo. Cloud-Native Buildpacks disponigas normigon tra platformoj subtenante la OCI-bildformaton, kiu certigas, ke la bildo povas esti prizorgita de la Docker-motoro.
Uzante la Spring Boot Kromprogramon
La kromaĵo Spring Boot konstruas OCI-bildojn el fonto uzante Buildpack. Bildoj estas kreitaj uzante bootBuildImagetaskoj (Gradle) aŭ spring-boot:build-imagecelo (Maven) kaj loka Docker-instalado.
Ni povas personecigi la nomon de la bildo, kiun ni devas puŝi al la Docker-registro specifante la nomon enen image tag:
De la eligo, ni vidas tion paketo Cloud-Native buildpackuzata por krei funkciantan OCI-bildon. Kiel antaŭe, ni povas vidi la bildon listigitan kiel bildon de Docker rulante la komandon:
Poste ni rulas la aldonaĵon Jib uzante la komandon Maven por konstrui la aplikaĵon kaj krei la ujan bildon. Kiel antaŭe, ni ne uzas iujn ajn Dockerfile ĉi tie:
Post ekzekuti la supran komandon de Maven, ni ricevas la sekvan eligon:
[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
La eligo montras, ke la ujo-bildo estis kreita kaj metita en la registron.
Instigoj kaj metodoj por krei optimumigitajn bildojn
Ni havas du ĉefajn kialojn por optimumigo:
Produkteco: En ujo-instrumentadsistemo, ujo-bildo estas tirita de la bildregistro al la gastiganto funkcianta la ujo-motoron. Ĉi tiu procezo nomiĝas planado. Eltiri grandajn bildojn el la registro rezultigas longajn planajn tempojn en kontenaj orkestradsistemoj kaj longajn konstrutempojn en CI-duktoj.
Sekureco: grandaj bildoj ankaŭ havas grandan areon por vundeblecoj.
Docker-bildo konsistas el stako de tavoloj, ĉiu reprezentante deklaron en nia Dockerfile. Ĉiu tavolo reprezentas la delton de ŝanĝoj en la subesta tavolo. Kiam ni tiras Docker-bildon el la registro, ĝi estas tirita en tavoloj kaj kaŝita sur la gastiganto.
Spring Boot uzas "grasa VASO" en kiel la defaŭlta pakformato. Kiam ni rigardas grasan BOĈON, ni vidas, ke la aplikaĵo estas tre malgranda parto de la tuta JAR. Ĉi tiu estas la parto, kiu plej ŝanĝiĝas. La resto konsistas el Spring Framework dependecoj.
La optimumiga formulo estas centrita ĉirkaŭ izolado de la aplikaĵo je aparta nivelo de la dependecoj de Spring Framework.
La dependeca tavolo, kiu formas la plej grandan parton de la dika JAR-dosiero, estas elŝutita nur unufoje kaj konservita en la gastiga sistemo.
Nur maldika tavolo de la aplikaĵo estas tirita dum la ĝisdatigoj de la aplikaĵo kaj planado de ujo, kiel montrite en ĉi tiu diagramo:
En la sekvaj sekcioj, ni rigardos kiel krei ĉi tiujn optimumigitajn bildojn por aplikaĵo Spring Boot.
Konstruado de Optimumigita Uja Bildo por Printempa Bota Apliko kun Buildpack
Spring Boot 2.3 subtenas tavoligon ĉerpante partojn de dika JAR-dosiero en apartajn tavolojn. La tavoliga funkcio estas malebligita defaŭlte kaj devas esti eksplicite ebligita per la kromaĵo Spring Boot Maven:
Ni uzos ĉi tiun agordon por konstrui nian ujan bildon unue kun Buildpack kaj poste kun Docker en la sekvaj sekcioj.
Ni kuru build-imageMaven celo krei ujan bildon:
mvn spring-boot:build-image
Se ni rulas Dive por vidi la tavolojn en la rezulta bildo, ni povas vidi, ke la aplika tavolo (ruĝe rondigita) estas multe pli malgranda en la kilobajta gamo kompare kun tio, kion ni akiris uzante la dikan JAR-formaton:
Konstruante Optimumigitan Ujan Bildon por Printempa Bota Apliko kun Docker
Anstataŭ uzi aldonaĵon Maven aŭ Gradle, ni ankaŭ povas krei tavoligitan Docker JAR-bildon kun Docker-dosiero.
Kiam ni uzas Docker, ni devas fari du kromajn paŝojn por ĉerpi la tavolojn kaj kopii ilin en la finan bildon.
La enhavo de la rezulta JAR post konstruado kun Maven kun tavoligado ebligita aspektos jene:
La eligo montras plian JAR nomitan spring-boot-jarmode-layertoolsи layersfle.idxdosiero. Ĉi tiu aldona JAR-dosiero disponigas tavoligkapablojn, kiel priskribite en la sekva sekcio.
Eltiru dependecojn sur apartaj tavoloj
Por vidi kaj ĉerpi tavolojn el nia tavoligita JAR, ni uzas la sisteman posedaĵon -Djarmode=layertoolspor komenco spring-boot-jarmode-layertoolsJAR anstataŭ aplikaĵo:
Ruli ĉi tiun komandon produktas eligon enhavantan la disponeblajn komandopciojn:
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
La eligo montras la komandojn list, extractи helpс helpestu la defaŭlta. Ni rulu la komandon kun listopcio:
java -Djarmode=layertools -jar target/usersignup-0.0.1-SNAPSHOT.jar list
Ni vidas liston de dependecoj kiuj povas esti aldonitaj kiel tavoloj.
Tavoloj defaŭlte:
Tavolnomo
Enhavo
dependencies
ajna dependeco, kies versio ne enhavas SNAPSHOT
spring-boot-loader
JAR-Ŝargilo-Klasoj
snapshot-dependencies
ajna dependeco, kies versio enhavas SNAPSHOT
application
aplikaj klasoj kaj rimedoj
Tavoloj estas difinitaj en layers.idxdosiero en la ordo en kiu ili devus esti aldonitaj al la Docker-bildo. Ĉi tiuj tavoloj estas konservitaj en kaŝmemoro sur la gastiganto post la unua alportado ĉar ili ne ŝanĝiĝas. Nur la ĝisdatigita aplikaĵa tavolo estas elŝutita al la gastiganto, kiu estas pli rapida pro la reduktita grandeco .
Konstruante bildon kun dependecoj ĉerpitaj en apartajn tavolojn
Ni konstruos la finan bildon en du paŝoj uzante metodon nomitan plurŝtupa asembleo . En la unua paŝo ni ĉerpos la dependecojn kaj en la dua paŝo ni kopios la ĉerpitajn dependecojn en la finan .
Ni modifu nian Dockerfile por plurŝtupa konstruo:
# 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"]
Ni konservas ĉi tiun agordon en aparta dosiero - Dockerfile2.
Ni konstruas la Docker-bildon per la komando:
docker build -f Dockerfile2 -t usersignup:v1 .
Post ekzekuto de ĉi tiu komando, ni ricevas la sekvan eligon:
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
Ni povas vidi, ke la bildo de Docker estas kreita kun bilda ID kaj poste etikedita.
Fine, ni rulas la Dive-komandon kiel antaŭe por kontroli la tavolojn ene de la generita Docker-bildo. Ni povas provizi bildan identigilon aŭ etikedon kiel enigon al la Dive-komando:
dive userssignup:v1
Kiel vi povas vidi el la eligo, la tavolo enhavanta la aplikaĵon nun estas nur 11 KB kaj la dependecoj estas konservitaj en apartaj tavoloj.
Eltiru internajn dependecojn sur apartaj tavoloj
Ni povas plu redukti la grandecon de la aplika tavolo ĉerpante iun ajn el niaj kutimaj dependecoj en apartan tavolon anstataŭ paki ilin per la aplikaĵo deklarante ilin en ymlsimila dosiero nomita layers.idx:
En ĉi tiu dosiero layers.idxni aldonis kutiman dependecon nomitan, io.myorgenhavanta organizajn dependecojn prenitajn de la komuna deponejo.
konkludo
En ĉi tiu artikolo, ni rigardis uzi Cloud-Native Buildpacks por konstrui ujan bildon rekte de la fonto. Ĉi tio estas alternativo al uzado de Docker por krei ujobildon laŭ la kutima maniero: unue, dika rulebla JAR-dosiero estas kreita kaj poste pakita en ujo-bildon specifante la instrukciojn en la Dockerfile.
Ni ankaŭ rigardis optimumigi nian ujon inkluzivante tavoligantan funkcion, kiu ĉerpas dependecojn en apartajn tavolojn, kiuj estas konservitaj en kaŝmemoro sur la gastiganto kaj maldika aplikaĵa tavolo estas ŝarĝita je planado en la ekzekutmotoroj de la ujo.
Vi povas trovi la tutan fontkodon uzatan en la artikolo ĉe GitHub .
Komando Referenco
Jen resumo de la komandoj, kiujn ni uzis en ĉi tiu artikolo por rapida referenco.
Kunteksta malplenigo:
docker system prune -a
Konstruante ujan bildon kun Dockerfile:
docker build -f <Docker file name> -t <tag> .
Konstruu ujobildon el fonto (sen Dockerfile):
mvn spring-boot:build-image
Rigardu dependecaj tavoloj. Antaŭ ol konstrui la aplikaĵan jardosieron, certigu, ke la tavoliga funkcio estas ebligita en la spring-boot-maven-plugin:
java -Djarmode=layertools -jar application.jar list
Ekstraktu dependecaj tavoloj. Antaŭ ol konstrui la aplikaĵan jardosieron, certigu, ke la tavoliga funkcio estas ebligita en la spring-boot-maven-plugin: