Spring Boot қолданбасы үшін оңтайландырылған Docker кескіндерін құру

Контейнерлер қолданбаны барлық бағдарламалық жасақтамаға және операциялық жүйеге тәуелділіктерімен орау, содан кейін оларды әртүрлі орталарға жеткізудің таңдаулы құралы болды.

Бұл мақала Spring Boot қолданбасын контейнерлеудің әртүрлі тәсілдерін қамтиды:

  • Docker файлын пайдаланып Docker кескінін жасау,
  • Cloud-Native Buildpack көмегімен көзден OCI кескінін жасау,
  • және көп деңгейлі құралдарды пайдалана отырып, JAR бөліктерін әртүрлі қабаттарға бөлу арқылы жұмыс уақытындағы кескінді оңтайландыру.

 Код мысалы

Бұл мақала жұмыс кодының мысалымен бірге беріледі GitHub арналған .

Контейнер терминологиясы

Біз мақалада қолданылатын контейнерлік терминологиядан бастаймыз:

  • Контейнер суреті: белгілі бір форматтағы файл. Біз құрастыру құралын іске қосу арқылы қолданбамызды контейнер кескініне түрлендіреміз.
  • Контейнер: Контейнер кескінінің орындалатын данасы.
  • Контейнер қозғалтқышы: Контейнерді іске қосуға жауапты демон процесі.
  • Контейнер хосты: Контейнер қозғалтқышы жұмыс істейтін негізгі компьютер.
  • Контейнер тізілімі: Контейнер кескінін жариялау және тарату үшін пайдаланылатын жалпы орын.
  • OCI стандартыАшық контейнерлік бастама (OCI) Linux Foundation ішінде құрылған жеңіл, ашық басқару құрылымы болып табылады. OCI кескінінің спецификациясы барлық контейнерлік қозғалтқыштардың кез келген құрастыру құралы арқылы жасалған контейнер кескіндерін іске қоса алатындығына көз жеткізу үшін контейнер кескіні мен жұмыс уақыты пішімдері үшін салалық стандарттарды анықтайды.

Қолданбаны контейнерлеу үшін біз қолданбамызды контейнер кескініне орап, сол суретті ортақ тізілімге жариялаймыз. Контейнердің орындалу уақыты бұл кескінді тізілімнен шығарып, оны қаптамадан шығарады және оның ішіндегі қолданбаны іске қосады.

Spring Boot бағдарламасының 2.3 нұсқасы OCI кескіндерін жасауға арналған плагиндерді қамтамасыз етеді.

Докер ең жиі қолданылатын контейнерді іске асыру болып табылады және біз мысалдарымызда Docker-ды қолданамыз, сондықтан осы мақаладағы барлық келесі контейнер сілтемелері Docker-ке сілтеме жасайды.

Контейнер кескінін дәстүрлі әдіспен құрастыру

Spring Boot қолданбалары үшін Docker кескіндерін жасау Docker файлына бірнеше нұсқауларды қосу арқылы өте оңай.

Біз алдымен орындалатын JAR файлын жасаймыз және Docker файл нұсқауларының бөлігі ретінде қажетті параметрлерді қолданғаннан кейін орындалатын JAR файлын негізгі JRE кескінінің үстіне көшіреміз.

Көктем қолданбасын жасайық Көктемгі инициализатор тәуелділіктермен 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 файлын жасайды. Docker қозғалтқышында жұмыс істеу үшін осы орындалатын JAR файлын Docker кескініне түрлендіру керек.

Контейнер кескінін жасау

Содан кейін біз осы орындалатын JAR файлын пәрменді орындау арқылы Docker кескініне орналастырамыз docker buildбұрын жасалған Dockerfile бар жобаның түбірлік каталогынан:

docker build  -t usersignup:v1 .

Пәрменді пайдаланып тізімдегі суретті көре аламыз:

docker images 

Жоғарыдағы пәрменнің нәтижесі біздің суретті қамтиды usersignupнегізгі суретпен бірге, adoptopenjdkDocker файлымызда көрсетілген.

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

Контейнер кескініндегі қабаттарды қарау

Кескіннің ішіндегі қабаттар дестесін қарастырайық. пайдаланамыз құрал  сүңгу осы қабаттарды көру үшін:

dive usersignup:v1

Мұнда Dive пәрменінің шығыс бөлігі: 

Spring Boot қолданбасы үшін оңтайландырылған Docker кескіндерін құру

Көріп отырғанымыздай, қолданбалы деңгей кескін өлшемінің едәуір бөлігін құрайды. Оңтайландырудың бір бөлігі ретінде келесі бөлімдерде осы қабаттың өлшемін азайтқымыз келеді.

Buildpack көмегімен контейнер кескінін жасау

Құрастыру пакеттері (Buildpacks) - бастапқы кодтан контейнер кескінін жасау үшін қызмет ретінде әртүрлі платформа (PAAS) ұсыныстарында қолданылатын жалпы термин. Оны Heroku 2011 жылы іске қосты және содан бері Cloud Foundry, Google App Engine, Gitlab, Knative және басқалары қабылдаған.

Spring Boot қолданбасы үшін оңтайландырылған Docker кескіндерін құру

Бұлтты құрастыру пакеттерінің артықшылығы

Кескіндерді жасау үшін 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-pluginpom.xml ішінде:

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

Содан кейін қолданбаны құру және контейнер кескінін жасау үшін Maven пәрменін пайдаланып Jib плагинін іске қосамыз. Бұрынғыдай, біз мұнда 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 тәуелділіктерінен тұрады.

Оңтайландыру формуласы қолданбаны Spring Framework тәуелділіктерінен бөлек деңгейде оқшаулауға бағытталған.

Қалың JAR файлының негізгі бөлігін құрайтын тәуелділік деңгейі тек бір рет жүктеледі және хост жүйесінде кэштеледі.

Қолданбаны жаңарту және контейнерді жоспарлау кезінде қолданбаның жұқа қабаты ғана тартылады. осы диаграммада көрсетілгендей:

Spring Boot қолданбасы үшін оңтайландырылған Docker кескіндерін құру

Келесі бөлімдерде 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 пішімін пайдалану арқылы алғанымызбен салыстырғанда килобайт ауқымында әлдеқайда аз екенін көреміз:

Spring Boot қолданбасы үшін оңтайландырылған Docker кескіндерін құру

Docker көмегімен Spring Boot қолданбасы үшін оңтайландырылған контейнер кескінін жасау

Maven немесе Gradle плагинін пайдаланудың орнына біз Docker файлы бар қабатты Docker JAR кескінін жасай аламыз.

Docker қолданбасын пайдаланған кезде қабаттарды шығарып, оларды соңғы кескінге көшіру үшін қосымша екі қадамды орындауымыз керек.

Қабаттау қосылған Maven көмегімен құрастырудан кейін алынған JAR мазмұны келесідей болады:

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-layertoolsҚолданбаның орнына JAR:

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 Loader кластары

snapshot-dependencies

нұсқасында SNAPSHOT бар кез келген тәуелділік

application

қолданбалы сыныптар мен ресурстар

Қабаттар ішінде анықталған layers.idxфайлды Docker кескініне қосу керек ретімен орналастырыңыз. Бұл қабаттар бірінші іздеуден кейін хостта кэштеледі, себебі олар өзгермейді. Хостқа тек жаңартылған қолданба қабаты жүктеледі, ол кішірейтілген өлшемге байланысты жылдамырақ .

Бөлек қабаттарға бөлінген тәуелділіктермен кескінді құру

деп аталатын әдіс арқылы соңғы кескінді екі кезеңде саламыз көп сатылы құрастыру . Бірінші қадамда біз тәуелділіктерді шығарамыз, ал екінші қадамда шығарылған тәуелділіктерді соңғы кескінге көшіреміз.

Көп сатылы құрастыру үшін Docker файлымызды өзгертейік:

# 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 кескіні кескін идентификаторымен жасалып, содан кейін тегтелгенін көреміз.

Соңында, жасалған Docker кескінінің ішіндегі қабаттарды тексеру үшін Dive пәрменін бұрынғыдай орындаймыз. Біз Dive пәрменіне кіріс ретінде сурет идентификаторын немесе тегті бере аламыз:

dive userssignup:v1

Шығарудан көріп отырғаныңыздай, қолданбаны қамтитын қабат енді тек 11 КБ құрайды және тәуелділіктер бөлек қабаттарда кэштелген. 

Spring Boot қолданбасы үшін оңтайландырылған Docker кескіндерін құру

Жеке қабаттарға ішкі тәуелділіктерді шығару

Біз кез келген реттелетін тәуелділіктерімізді оларды қосымшада жариялау арқылы қолданбамен қаптаманың орнына бөлек деңгейге шығарып, қолданба деңгейінің өлшемін одан әрі азайта аламыз. 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>

Ақпарат көзі: www.habr.com