Bati imaj Docker optimize pou yon aplikasyon Spring Boot

Kontenè yo te vin pi pito mwayen pou anbalaj yon aplikasyon ak tout lojisyèl li yo ak depandans sistèm operasyon yo ak Lè sa a, delivre yo nan diferan anviwònman.

Atik sa a kouvri diferan fason pou mete yon aplikasyon Spring Boot:

  • kreye yon imaj Docker lè l sèvi avèk yon dosye Docker,
  • kreye yon imaj OCI soti nan sous lè l sèvi avèk Cloud-Native Buildpack,
  • ak optimize imaj nan tan an lè yo separe pati JAR nan diferan kouch lè l sèvi avèk zouti milti-kouch.

 Egzanp kòd

Atik sa a akonpaye pa egzanp kòd k ap travay sou GitHub .

Teknoloji veso

Nou pral kòmanse ak tèminoloji veso yo itilize nan atik la:

  • Imaj veso: dosye nan yon fòma espesifik. Nou pral konvèti aplikasyon nou an nan yon imaj veso lè nou kouri zouti bati a.
  • Veso: Yon egzanp ègzekutabl imaj veso a.
  • Motè veso: Pwosesis demon ki responsab pou kouri veso a.
  • Lame veso: Òdinatè lame sou kote motè veso a kouri.
  • Rejis veso: Kote jeneral yo itilize pou pibliye ak distribye imaj veso a.
  • OCI estandaOpen Container Initiative (OCI) se yon estrikti gouvènans ki lejè, ouvè ki fòme nan Linux Foundation. OCI Image Specification defini estanda endistri pou imaj veso ak fòma egzekite pou asire ke tout motè veso yo ka kouri imaj veso ki kreye pa nenpòt zouti konstriksyon.

Pou mete yon aplikasyon nan kontenè, nou vlope aplikasyon nou an nan yon imaj veso epi nou pibliye imaj sa a nan yon rejis pataje. Ègzekutabl veso a rekipere imaj sa a nan rejis la, depake li, epi kouri aplikasyon an andedan li.

Vèsyon 2.3 nan Spring Boot bay grefon pou kreye imaj OCI.

Koupre se aplikasyon veso ki pi souvan itilize, epi nou itilize Docker nan egzanp nou yo, kidonk tout referans veso ki vin apre nan atik sa a pral refere a Docker.

Bati yon imaj veso fason tradisyonèl la

Kreye imaj Docker pou aplikasyon Spring Boot se trè fasil lè w ajoute kèk enstriksyon nan dosye Docker la.

Nou premye kreye yon dosye JAR ègzèkutabl epi, kòm yon pati nan enstriksyon yo dosye Docker, kopye dosye JAR ègzèkutabl la sou tèt imaj JRE baz la apre w fin aplike paramèt ki nesesè yo.

Ann kreye aplikasyon Spring nou an sou Spring Inisyalizr ak depandans weblombokи actuator. Nou ap ajoute tou yon kontwolè rès pou bay yon API GETmetòd.

Kreye yon Dockerfile

Lè sa a, nou containerize aplikasyon sa a lè nou ajoute Dockerfile:

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

Fichye Docker nou an gen yon imaj de baz adoptopenjdk, sou tèt li nou kopye fichye JAR nou an ak Lè sa a, louvri pò a, 8080ki pral koute demann.

Bati aplikasyon an

Premye ou bezwen kreye yon aplikasyon lè l sèvi avèk Maven oswa Gradle. Isit la nou itilize Maven:

mvn clean package

Sa a kreye yon dosye JAR ègzekutabl pou aplikasyon an. Nou bezwen konvèti JAR ègzèkutabl sa a nan yon imaj Docker pou kouri sou motè Docker la.

Kreye yon imaj veso

Lè sa a, nou mete dosye sa a ègzèkutabl JAR nan imaj la Docker pa kouri lòd la docker buildsoti nan anyè rasin pwojè a ki gen Dockerfile ki te kreye pi bonè:

docker build  -t usersignup:v1 .

Nou ka wè imaj nou an nan lis la lè l sèvi avèk kòmandman an:

docker images 

Pwodiksyon an nan lòd ki anwo a gen ladan imaj nou an usersignupansanm ak imaj de baz la, adoptopenjdkespesifye nan dosye Docker nou an.

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

Gade kouch andedan yon imaj veso

Ann gade nan pil la nan kouch andedan imaj la. Nou pral itilize zouti  plonje pou wè kouch sa yo:

dive usersignup:v1

Isit la se yon pati nan pwodiksyon an nan lòd la plonje: 

Bati imaj Docker optimize pou yon aplikasyon Spring Boot

Kòm nou ka wè, kouch aplikasyon an fè yon pati enpòtan nan gwosè imaj la. Nou vle redwi gwosè kouch sa a nan seksyon sa yo kòm yon pati nan optimize nou an.

Kreye yon imaj veso lè l sèvi avèk Buildpack

Pakè asanble yo (Buildpacks) se yon tèm jeneral yo itilize pa divès kalite ofrann Platfòm kòm yon Sèvis (PAAS) pou kreye yon imaj veso ki soti nan kòd sous. Li te lanse pa Heroku nan 2011 e li te adopte pa Cloud Foundry, Google App Engine, Gitlab, Knative ak plizyè lòt.

Bati imaj Docker optimize pou yon aplikasyon Spring Boot

Avantaj nan pakè konstriksyon nwaj yo

Youn nan benefis prensipal yo nan itilize Buildpack pou kreye imaj se sa Chanjman konfigirasyon imaj yo ka jere santralman (builder) epi pwopaje nan tout aplikasyon lè l sèvi avèk builder.

Pakè yo bati yo te byen makonnen ak platfòm la. Cloud-Native Buildpacks bay normalisation atravè platfòm yo lè yo sipòte fòma imaj OCI a, ki asire ke motè Docker a ka kouri imaj la.

Sèvi ak Plugin Spring Boot la

Plugin Spring Boot la bati imaj OCI soti nan sous lè l sèvi avèk Buildpack. Imaj yo kreye lè l sèvi avèk bootBuildImagetravay (Gradle) oswa spring-boot:build-imagesib (Maven) ak enstalasyon Docker lokal yo.

Nou ka Customize non imaj ki nesesè pou pouse nan rejis Docker lè nou espesifye non an 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>

Ann sèvi ak Maven pou fè li build-imageobjektif pou kreye yon aplikasyon ak kreye yon imaj veso. Nou pa sèvi ak okenn Dockerfile nan moman sa a.

mvn spring-boot:build-image

Rezilta a pral yon bagay tankou sa a:

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

Soti nan pwodiksyon an nou wè sa paketo Cloud-Native buildpackitilize pou kreye yon imaj OCI k ap travay. Kòm anvan, nou ka wè imaj la ki nan lis kòm yon imaj Docker lè nou kouri lòd la:

docker images 

Konklizyon:

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

Kreye yon imaj veso lè l sèvi avèk Jib

Jib se yon plugin kreyasyon imaj soti nan Google ki bay yon metòd altènatif pou kreye yon imaj veso ki soti nan kòd sous.

Konfigirasyon jib-maven-pluginnan pom.xml:

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

Apre sa, nou kouri Plugin Jib la lè l sèvi avèk lòd Maven pou konstwi aplikasyon an epi kreye yon imaj veso. Kòm anvan, nou pa itilize okenn dosye Docker isit la:

mvn compile jib:build -Dimage=<docker registry name>/usersignup:v1

Apre egzekite lòd Maven ki anwo a, nou jwenn pwodiksyon sa a:

[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

Pwodiksyon an montre ke imaj veso a te kreye epi mete l nan rejis la.

Motivasyon ak teknik pou kreye imaj optimize

Nou gen de rezon prensipal pou optimize:

  • Pwodiktivite: Nan yon sistèm òkestrasyon veso, yo rekipere yon imaj veso ki soti nan rejis imaj la nan lame ki kouri motè veso a. Pwosesis sa a rele planifikasyon. Rale gwo imaj ki soti nan rejis la rezilta nan tan orè long nan sistèm orchestration veso ak tan bati long nan tiyo CI.
  • Безопасность: Pi gwo imaj yo genyen tou yon pi gwo zòn pou frajilite yo.

Yon imaj Docker konsiste de yon pil kouch, chak nan yo ki reprezante yon enstriksyon nan Dockerfile nou an. Chak kouch reprezante yon delta nan chanjman ki fèt nan kouch kache a. Lè nou rale yon imaj Docker soti nan rejis la, li rale nan kouch ak kach sou lame a.

Spring Boot itilize "Grès JAR" nan kòm fòma anbalaj default. Lè nou gade JAR epè a, nou wè aplikasyon an fè yon ti pòsyon nan JAR tout antye. Sa a se pati ki chanje pi souvan. Rès la konsiste de depandans Spring Framework yo.

Fòmil optimize a konsantre sou izole aplikasyon an nan yon nivo separe ak depandans Spring Framework.

Kouch depandans la, ki fòme pi gwo fichye JAR epè a, telechaje yon sèl fwa epi yo kache sou sistèm lame a.

Se sèlman yon kouch mens nan aplikasyon an rale pandan mizajou aplikasyon an ak orè veso. jan yo montre nan dyagram sa a:

Bati imaj Docker optimize pou yon aplikasyon Spring Boot

Nan seksyon sa yo, nou pral gade ki jan yo kreye imaj optimize sa yo pou yon aplikasyon Spring Boot.

Kreye yon imaj veso optimize pou yon aplikasyon Spring Boot lè l sèvi avèk Buildpack

Spring Boot 2.3 sipòte kouch pa ekstrè pati nan yon dosye JAR epè nan kouch separe. Karakteristik stratifikasyon an enfim pa default epi yo dwe aktive klèman lè l sèvi avèk Plugin Spring Boot Maven:

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

Nou pral sèvi ak konfigirasyon sa a pou konstwi imaj veso nou an premye ak Buildpack epi answit ak Docker nan seksyon sa yo.

Ann lanse build-imageMaven sib pou kreye imaj veso:

mvn spring-boot:build-image

Si nou kouri plonje pou wè kouch yo nan imaj la ki kapab lakòz, nou ka wè ke kouch aplikasyon an (ki dekri an wouj) se pi piti anpil nan seri a kilobyte konpare ak sa nou te resevwa lè l sèvi avèk fòma JAR la epè:

Bati imaj Docker optimize pou yon aplikasyon Spring Boot

Kreye yon imaj veso optimize pou yon aplikasyon Spring Boot lè l sèvi avèk Docker

Olye pou nou itilize yon Plugin Maven oswa Gradle, nou ka kreye tou yon imaj Docker JAR kouch ak yon dosye Docker.

Lè nou itilize Docker, nou bezwen fè de etap adisyonèl pou ekstrè kouch yo epi kopye yo nan imaj final la.

Sa ki nan JAR ki kapab lakòz apre yo fin bati lè l sèvi avèk Maven ak kouch pèmèt yo pral sanble sa a:

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

Pwodiksyon an montre yon JAR adisyonèl yo te rele spring-boot-jarmode-layertoolsи layersfle.idxdosye. Fichye JAR adisyonèl sa a bay kapasite pwosesis kouch, jan sa dekri nan pwochen seksyon an.

Èkstraksyon depandans sou kouch endividyèl yo

Pou wè ak ekstrè kouch nan JAR kouch nou an, nou itilize pwopriyete sistèm lan -Djarmode=layertoolspou kòmanse spring-boot-jarmode-layertoolsJAR olye pou yo aplikasyon:

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

Kouri lòd sa a pwodui pwodiksyon ki gen opsyon kòmand ki disponib yo:

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

Pwodiksyon an montre kòmandman yo listextractи helpс helpdwe default la. Ann kouri kòmandman an ak listopsyon:

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

Nou wè yon lis depandans ki ka ajoute kòm kouch.

Kouch default:

Non kouch

Content

dependencies

nenpòt depandans ki gen vèsyon pa genyen SNAPSHOT

spring-boot-loader

JAR Loader Klas

snapshot-dependencies

nenpòt depandans ki gen vèsyon ki gen SNAPSHOT

application

klas aplikasyon ak resous yo

Kouch yo defini nan layers.idxdosye nan lòd yo ta dwe ajoute nan imaj la Docker. Kouch sa yo kach nan lame a apre premye rekiperasyon an paske yo pa chanje. Se sèlman kouch aplikasyon an mete ajou telechaje nan lame a, ki se pi vit akòz gwosè a redwi .

Bati yon imaj ak depandans ekstrè nan kouch separe

Nou pral bati imaj final la nan de etap lè l sèvi avèk yon metòd yo rele asanble milti-etap . Nan premye etap la nou pral ekstrè depandans yo ak nan dezyèm etap la nou pral kopye depandans yo ekstrè nan imaj final la.

Ann modifye Dockerfile nou an pou yon bati plizyè etap:

# 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"]

Nou sove konfigirasyon sa a nan yon dosye separe - Dockerfile2.

Nou bati imaj la Docker lè l sèvi avèk kòmandman an:

docker build -f Dockerfile2 -t usersignup:v1 .

Apre kouri lòd sa a nou jwenn pwodiksyon sa a:

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

Nou ka wè ke yon imaj Docker kreye ak yon ID imaj ak Lè sa a, tag.

Finalman, nou kouri lòd la plonje tankou anvan yo enspekte kouch yo andedan imaj la Docker pwodwi. Nou ka bay yon ID imaj oswa tag kòm opinyon nan lòd la plonje:

dive userssignup:v1

Kòm ou ka wè nan pwodiksyon an, kouch ki gen aplikasyon an se kounye a sèlman 11 KB, ak depandans yo kachèt nan kouch separe. 

Bati imaj Docker optimize pou yon aplikasyon Spring Boot

Èkstraksyon depandans entèn sou kouch endividyèl yo

Nou ka diminye plis gwosè nivo aplikasyon an lè nou retire nenpòt nan depandans koutim nou yo nan yon nivo separe olye pou nou anbalaj yo ak aplikasyon an lè nou deklare yo nan ymldosye ki sanble non 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/"

Nan dosye sa a layers.idxnou te ajoute yon depandans koutim ki rele, io.myorgki gen depandans òganizasyon rekipere nan yon depo pataje.

Sòti

Nan atik sa a, nou te gade lè l sèvi avèk Cloud-Native Buildpacks pou konstwi yon imaj veso ki soti dirèkteman nan kòd sous. Sa a se yon altènativ a lè l sèvi avèk Docker pou kreye yon imaj veso fason nòmal: premye kreye yon epè ègzèkutabl JAR fichye epi answit anbalaj li nan yon imaj veso lè w espesifye enstriksyon nan fichye Docker la.

Nou te gade tou nan optimize veso nou an pa pèmèt yon karakteristik stratifikasyon ki ekstrè depandans nan kouch separe ki nan kachèt sou lame a ak yon kouch mens nan aplikasyon an chaje nan tan orè nan motè ekzekisyon veso a.

Ou ka jwenn tout kòd sous yo itilize nan atik la nan Github .

Referans kòmand

Isit la nan yon kourikoulòm rapid nan kòmandman yo nou te itilize nan atik sa a.

Netwaye kontèks:

docker system prune -a

Kreye yon imaj veso lè l sèvi avèk yon dosye Docker:

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

Nou bati imaj veso a soti nan kòd sous la (san Dockerfile):

mvn spring-boot:build-image

Gade kouch depandans. Anvan ou bati dosye JAR aplikasyon an, asire w ke karakteristik stratifikasyon an aktive nan spring-boot-maven-plugin:

java -Djarmode=layertools -jar application.jar list

Èkstraksyon kouch depandans. Anvan ou bati dosye JAR aplikasyon an, asire w ke karakteristik stratifikasyon an aktive nan spring-boot-maven-plugin:

 java -Djarmode=layertools -jar application.jar extract

Gade yon lis imaj veso yo

docker images

Gade sou bò gòch anndan imaj veso a (asire w ke zouti plonje a enstale):

dive <image ID or image tag>

Sous: www.habr.com