Эҷоди тасвирҳои оптимизатсияшудаи Docker барои барномаи Spring Boot

Контейнерҳо ба воситаи бартарии бастабандии барнома бо тамоми вобастагии нармафзор ва системаи оператсионии он ва интиқоли онҳо ба муҳитҳои гуногун табдил ёфтаанд.

Ин мақола роҳҳои гуногуни контейнер кардани замимаи Spring Boot-ро дар бар мегирад:

  • сохтани тасвири Docker бо истифода аз файли Docker,
  • сохтани тасвири OCI аз манбаъ бо истифода аз Cloud-Native Buildpack,
  • ва оптимизатсияи тасвири вақти корӣ тавассути ҷудо кардани қисмҳои JAR ба қабатҳои гуногун бо истифода аз абзорҳои бисёрсатҳа.

 Намунаи код

Ин мақола бо мисоли коди корӣ ҳамроҳ карда мешавад дар GitHub .

Терминологияи контейнер

Мо бо истилоҳоти контейнерӣ, ки дар мақола истифода шудааст, оғоз мекунем:

  • Тасвири контейнер: файли формати мушаххас. Мо замимаи худро ба тасвири контейнер табдил медиҳем, ки воситаи сохтани асбобро иҷро мекунад.
  • Контейнер: Намунаи иҷрошавандаи тасвири контейнер.
  • Муҳаррики контейнер: Раванди демон, ки барои идора кардани контейнер масъул аст.
  • Хости контейнер: Компютери асосӣ, ки дар он муҳаррики контейнер кор мекунад.
  • Феҳристи контейнерҳо: Ҷойгоҳи умумӣ барои интишор ва паҳн кардани тасвири контейнер истифода мешавад.
  • Стандарти OCIТашаббуси контейнери кушод (OCI) сохтори сабук ва кушодаи идоракунӣ мебошад, ки дар доираи Бунёди Linux ташкил шудааст. Мушаххасоти тасвири OCI стандартҳои саноатиро барои тасвири контейнер ва форматҳои вақти корӣ муайян мекунад, то кафолат диҳад, ки ҳама муҳаррикҳои контейнер метавонанд тасвирҳои контейнериро, ки аз ҷониби ҳама асбоби сохтмон сохта шудаанд, иҷро кунанд.

Барои контейнер кардани барнома, мо замимаи худро дар тасвири контейнер мепӯшем ва он тасвирро дар феҳристи муштарак нашр мекунем. Вақти иҷроиши контейнер ин тасвирро аз реестр бармегардонад, онро мекушояд ва барномаро дар дохили он иҷро мекунад.

Версияи 2.3-и Spring Boot плагинҳоро барои эҷоди тасвирҳои OCI таъмин мекунад.

Доктор татбиқи контейнерҳои маъмултарин аст ва мо дар мисолҳои худ Docker-ро истифода мебарем, аз ин рӯ ҳама истинодҳои минбаъдаи контейнер дар ин мақола ба Docker муроҷиат мекунанд.

Сохтани тасвири контейнер бо роҳи анъанавӣ

Эҷоди тасвирҳои Docker барои замимаҳои Spring Boot бо илова кардани чанд дастур ба файли Docker хеле осон аст.

Мо аввал файли иҷрошавандаи JAR эҷод мекунем ва ҳамчун як қисми дастурҳои файли Docker, пас аз татбиқи танзимоти зарурӣ файли иҷрошавандаи JAR-ро дар болои тасвири асосии JRE нусхабардорӣ мекунем.

Биёед барномаи баҳори худро дар он созем Initializr баҳор бо вобастагӣ weblombokи actuator. Мо инчунин як контролери истироҳатро барои таъмин кардани API илова мекунем GETусул.

Эҷоди файли Docker

Пас аз он мо ин барномаро бо илова кардан контейнер мекунем Dockerfile:

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

Файли Docker мо дорои тасвири асосӣ аз adoptopenjdk, ки дар болои он мо файли JAR-и худро нусхабардорӣ мекунем ва сипас портро мекушоем, 8080ки дархостхоро мешунавад.

Сохтани барнома

Аввалан шумо бояд бо истифода аз Maven ё Gradle барнома эҷод кунед. Дар ин ҷо мо Maven-ро истифода мебарем:

mvn clean package

Ин барои барнома файли иҷрошавандаи JAR эҷод мекунад. Мо бояд ин JAR-и иҷрошавандаро ба тасвири Docker табдил диҳем, то дар муҳаррики Docker кор кунем.

Эҷоди тасвири контейнер

Сипас, мо ин файли иҷрошавандаи JAR-ро ба тасвири Docker бо иҷро кардани фармон мегузорем docker buildаз директорияи решавӣ лоиҳа, ки дорои Dockerfile қаблан сохта шудааст:

docker build  -t usersignup:v1 .

Мо метавонем тасвири худро дар рӯйхат бо истифода аз фармон бубинем:

docker images 

Натиҷаи фармони боло тасвири моро дар бар мегирад usersignupдар баробари тасвири асосӣ, adoptopenjdkдар файли Docker мо нишон дода шудааст.

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

Намоиши қабатҳои дохили тасвири контейнер

Биёед ба анбори қабатҳои дохили тасвир назар кунем. истифода мебарем восита  ғарқ шудан Барои дидани ин қабатҳо:

dive usersignup:v1

Ин аст як қисми баромади фармони Dive: 

Эҷоди тасвирҳои оптимизатсияшудаи Docker барои барномаи Spring Boot

Тавре ки мо мебинем, қабати барнома қисми зиёди андозаи тасвирро ташкил медиҳад. Мо мехоҳем андозаи ин қабатро дар бахшҳои зерин ҳамчун як қисми оптимизатсияи худ кам кунем.

Эҷоди тасвири контейнер бо истифода аз Buildpack

Бастаҳои васлкунӣ (Сохтани бастаҳо) истилоҳи умумӣест, ки аз ҷониби пешниҳодҳои гуногуни Платформа ҳамчун хидмат (PAAS) барои эҷоди тасвири контейнерӣ аз рамзи сарчашма истифода мешавад. Он аз ҷониби Ҳероку дар соли 2011 ба кор андохта шуд ва аз он замон аз ҷониби Cloud Foundry, Google App Engine, Gitlab, Knative ва чанде дигар қабул карда шуд.

Эҷоди тасвирҳои оптимизатсияшудаи Docker барои барномаи Spring Boot

Бартарии бастаҳои сохтани абр

Яке аз бартариҳои асосии истифодаи Buildpack барои эҷоди тасвирҳо дар он аст Тағироти конфигуратсияи тасвирро метавон ба таври мутамарказ идора кард (созанда) ва ба ҳама барномаҳо бо истифода аз созанда паҳн карда шавад.

Бастаҳои сохтмонӣ ба платформа зич пайваст карда шуданд. Cloud-Native Buildpacks стандартизатсияро дар платформаҳо тавассути дастгирии формати тасвири OCI таъмин мекунад, ки кафолат медиҳад, ки тасвир аз ҷониби муҳаррики Docker идора карда шавад.

Истифодаи плагини Spring Boot

Васлкунаки Spring Boot бо истифода аз Buildpack тасвирҳои OCI-ро аз манбаъ месозад. Тасвирҳо бо истифода аз он сохта мешаванд bootBuildImageвазифаҳо (Gradle) ё spring-boot:build-imageҳадафҳо (Maven) ва насби маҳаллии Docker.

Мо метавонем номи тасвиреро, ки барои ворид шудан ба реестри Docker лозим аст, бо нишон додани ном дар 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>

Биёед барои ин кор Maven-ро истифода барем build-imageҳадафҳо барои эҷоди барнома ва эҷоди тасвири контейнер. Мо дар айни замон ягон файли Docker-ро истифода намебарем.

mvn spring-boot:build-image

Натиҷа чунин хоҳад буд:

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

Аз баромадхо мо инро мебинем paketo Cloud-Native buildpackбарои эҷоди тасвири кории OCI истифода мешавад. Мисли пештара, мо метавонем тасвири ҳамчун тасвири Docker рӯйхатшударо тавассути иҷро кардани фармон бинем:

docker images 

Хулоса:

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

Эҷоди тасвири контейнер бо истифода аз Jib

Jib як плагини эҷоди тасвир аз Google мебошад, ки усули алтернативии эҷоди тасвири контейнерро аз коди сарчашма таъмин мекунад.

Танзимот jib-maven-pluginдар pom.xml:

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

Баъдан, мо плагини Jib-ро бо истифода аз фармони Maven барои сохтани барнома ва эҷоди тасвири контейнер иҷро мекунем. Мисли пештара, мо дар ин ҷо ягон файли Docker истифода намебарем:

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

Пас аз иҷрои фармони Maven, мо натиҷаи зеринро мегирем:

[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

Натиҷа нишон медиҳад, ки тасвири контейнер сохта шудааст ва дар реестр ҷойгир шудааст.

Ҳавасмандкунӣ ва усулҳо барои эҷоди тасвирҳои оптимизатсияшуда

Мо ду сабаби асосии оптимизатсия дорем:

  • Маҳсулнокӣ: Дар системаи оркестрсозии контейнер, тасвири контейнер аз феҳристи тасвирҳо ба ҳост, ки муҳаррики контейнерро идора мекунад, гирифта мешавад. Ин раванд банақшагирӣ номида мешавад. Гирифтани тасвирҳои калон аз феҳрист боиси банақшагирии тӯлонӣ дар системаҳои оркестрсозии контейнер ва вақтҳои тӯлонии сохтмон дар лӯлаҳои CI мегардад.
  • Амният: Тасвирҳои калонтар инчунин барои осебпазирӣ майдони васеътар доранд.

Тасвири Docker аз як стек қабатҳо иборат аст, ки ҳар яки онҳо дастурро дар Dockerfile мо ифода мекунанд. Ҳар як қабат як дельтаи тағиротро дар қабати зеризаминӣ ифода мекунад. Вақте ки мо тасвири Docker-ро аз реестр мекашем, он ба қабатҳо кашида мешавад ва дар мизбон кэш карда мешавад.

Истифодаи Spring Boot "ҶАР фарбеҳ" дар ҳамчун формати бастабандии пешфарз. Вақте ки мо ба JAR-и ғафс назар мекунем, мо мебинем, ки барнома як қисми хеле ками тамоми JAR-ро ташкил медиҳад. Ин қисмест, ки аксар вақт тағир меёбад. Қисми боқимонда аз вобастагии чаҳорчӯбаи баҳор иборат аст.

Формулаи оптимизатсия ба ҷудо кардани барнома дар сатҳи алоҳида аз вобастагии Spring Framework нигаронида шудааст.

Қабати вобастагӣ, ки қисми асосии файли ғафси JAR-ро ташкил медиҳад, танҳо як маротиба зеркашӣ карда мешавад ва дар системаи ҳост кэш карда мешавад.

Ҳангоми навсозии барномаҳо ва банақшагирии контейнер танҳо як қабати тунуки барнома кашида мешавад. чунон ки дар ин диаграмма нишон дода шудааст:

Эҷоди тасвирҳои оптимизатсияшудаи Docker барои барномаи Spring Boot

Дар бахшҳои зерин мо дида мебароем, ки чӣ гуна ин тасвирҳои оптимизатсияшуда барои барномаи Spring Boot эҷод кардан мумкин аст.

Эҷоди тасвири оптимизатсияшудаи контейнер барои замимаи баҳорӣ бо истифода аз Buildpack

Spring Boot 2.3 қабатро тавассути истихроҷи қисмҳои файли ғафси JAR ба қабатҳои алоҳида дастгирӣ мекунад. Хусусияти қабатбандӣ бо нобаёнӣ ғайрифаъол аст ва бояд бо истифода аз плагини Spring Boot Maven ба таври возеҳ фаъол карда шавад:

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

Мо ин конфигуратсияро барои сохтани тасвири контейнерии худ аввал бо Buildpack ва баъд бо Docker дар бахшҳои зерин истифода хоҳем кард.

Биёед оғоз кунем build-imageҲадафи Maven барои эҷоди тасвири контейнер:

mvn spring-boot:build-image

Агар мо Dive-ро барои дидани қабатҳои тасвири натиҷавӣ иҷро кунем, мо мебинем, ки қабати барнома (бо ранги сурх нишон дода шудааст) дар муқоиса бо формати ғафси JAR дар диапазони килобайт хеле хурдтар аст:

Эҷоди тасвирҳои оптимизатсияшудаи Docker барои барномаи Spring Boot

Эҷоди тасвири оптимизатсияшудаи контейнер барои замимаи баҳорӣ бо истифода аз Docker

Ба ҷои истифодаи плагини Maven ё Gradle, мо инчунин метавонем тасвири қабати Docker JAR-ро бо файли Docker эҷод кунем.

Вақте ки мо Docker-ро истифода мебарем, мо бояд ду қадами иловагиро барои истихроҷи қабатҳо ва нусхабардории онҳо ба тасвири ниҳоӣ иҷро кунем.

Мундариҷаи JAR-и натиҷавӣ пас аз сохтани Maven бо қабати фаъол чунин хоҳад буд:

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

Дар натиҷа як JAR иловагӣ бо номи нишон дода мешавад spring-boot-jarmode-layertoolsи layersfle.idxфайл. Ин файли иловагии JAR имкониятҳои коркарди қабатро таъмин мекунад, тавре ки дар боби оянда тавсиф шудааст.

Истихроҷи вобастагӣ аз қабатҳои инфиродӣ

Барои дидан ва истихроҷи қабатҳо аз JAR қабати мо, мо моликияти системаро истифода мебарем -Djarmode=layertoolsбарои оғоз spring-boot-jarmode-layertoolsJAR ба ҷои барнома:

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

Иҷрои ин фармон натиҷаеро медиҳад, ки дорои имконоти дастраси фармон аст:

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

Натиҷа фармонҳоро нишон медиҳад listextractи helpс helpпешфарз бошад. Биёед фармонро бо listвариант:

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

Мо рӯйхати вобастагиҳоро мебинем, ки онҳоро ҳамчун қабатҳо илова кардан мумкин аст.

Қабатҳои пешфарз:

Номи қабат

Мундариҷа

dependencies

ҳама гуна вобастагӣ, ки версияи он SNAPSHOT надорад

spring-boot-loader

Синфҳои боркунаки JAR

snapshot-dependencies

ҳама гуна вобастагӣ, ки версияи он SNAPSHOT дорад

application

синфҳои татбиқ ва захираҳо

Қабатҳо дар layers.idxфайл бо тартибе, ки онҳо бояд ба тасвири Docker илова карда шаванд. Ин қабатҳо пас аз ҷустуҷӯи аввал дар мизбон кэш карда мешаванд, зеро онҳо тағир намеёбанд. Танҳо қабати замимаи навшуда ба мизбон бор карда мешавад, ки аз сабаби кам шудани андозаи он тезтар аст .

Сохтани тасвир бо вобастагӣ ба қабатҳои алоҳида

Мо тасвири ниҳоиро дар ду марҳила бо истифода аз усули номбаршуда месозем монтажи бисёрсоҳавӣ . Дар қадами аввал мо вобастагиҳоро истихроҷ мекунем ва дар қадами дуюм вобастагиҳои истихроҷшударо ба тасвири ниҳоӣ нусхабардорӣ мекунем.

Биёед Dockerfile-и худро барои сохтани бисёрмарҳила тағир диҳем:

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

Мо ин конфигуратсияро дар файли алоҳида захира мекунем - Dockerfile2.

Мо тасвири Docker-ро бо истифода аз фармони:

docker build -f Dockerfile2 -t usersignup:v1 .

Пас аз иҷро кардани ин фармон мо натиҷаи зеринро мегирем:

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

Мо мебинем, ки тасвири Docker бо ID-и тасвир сохта мешавад ва сипас барчасп карда мешавад.

Ниҳоят, мо фармони Dive-ро мисли пештара иҷро мекунем, то қабатҳои дохили тасвири тавлидшудаи Docker-ро тафтиш кунем. Мо метавонем ID тасвир ё барчаспро ҳамчун вуруд ба фармони Dive пешниҳод кунем:

dive userssignup:v1

Тавре ки шумо дар натиҷа мебинед, қабати дорои барнома ҳоло ҳамагӣ 11 КБ аст ва вобастагӣ дар қабатҳои алоҳида кэш карда мешаванд. 

Эҷоди тасвирҳои оптимизатсияшудаи Docker барои барномаи Spring Boot

Истихроҷи вобастагии дохилӣ аз қабатҳои инфиродӣ

Мо метавонем минбаъд андозаи сатҳи барномаро тавассути истихроҷи ҳама гуна вобастагии фармоишии мо ба сатҳи алоҳида ба ҷои бастабандии онҳо бо замима тавассути эълон кардани онҳо кам кунем. ymlфайли монанд ном дорад 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/"

Дар ин файл layers.idxмо вобастагии фармоиширо илова кардем, ки ном дорад, io.myorgдорои вобастагии созмон, ки аз анбори муштарак гирифта шудаанд.

хулоса

Дар ин мақола, мо истифодаи Cloud-Native Buildpacks-ро барои сохтани тасвири контейнер мустақиман аз рамзи сарчашма дида баромадем. Ин алтернатива барои истифодаи Docker барои эҷоди тасвири контейнерӣ бо роҳи муқаррарӣ аст: аввал файли ғафси иҷрошавандаи JAR эҷод кунед ва сипас онро ба тасвири контейнер бо роҳи муайян кардани дастурҳо дар файли Docker баста кунед.

Мо инчунин оптимизатсияи контейнери худро тавассути фаъол кардани як хусусияти қабатсозӣ дида баромадем, ки вобастагиҳоро ба қабатҳои алоҳида, ки дар ҳост кэш карда мешаванд ва қабати тунуки барнома дар вақти банақшагирӣ дар муҳаррикҳои иҷрокунандаи контейнер бор карда мешавад.

Шумо метавонед ҳама рамзи сарчашмаеро, ки дар мақола истифода шудааст, дар ин ҷо пайдо кунед Github .

Истиноди фармон

Ин аст мухтасари фармонҳои мо дар ин мақола.

Тозакунии контекст:

docker system prune -a

Эҷоди тасвири контейнер бо истифода аз файли Docker:

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

Мо тасвири контейнерро аз коди ибтидоӣ месозем (бе Dockerfile):

mvn spring-boot:build-image

Дидани қабатҳои вобастагӣ. Пеш аз сохтани файли барномаи JAR, боварӣ ҳосил кунед, ки хусусияти қабатбандӣ дар spring-boot-maven-plugin фаъол аст:

java -Djarmode=layertools -jar application.jar list

Истихроҷи қабатҳои вобастагӣ. Пеш аз сохтани файли барномаи JAR, боварӣ ҳосил кунед, ки хусусияти қабатбандӣ дар spring-boot-maven-plugin фаъол аст:

 java -Djarmode=layertools -jar application.jar extract

Рӯйхати тасвирҳои контейнерро бинед

docker images

Дар тарафи чапи дохили тасвири контейнер дидан кунед (боварӣ ҳосил кунед, ки асбоби ғаввосӣ насб шудааст):

dive <image ID or image tag>

Манбаъ: will.com