ProHoster > Օրագիր > Վարչակազմը > Օպտիմիզացված Docker պատկերների ստեղծում Spring Boot հավելվածի համար
Օպտիմիզացված Docker պատկերների ստեղծում Spring Boot հավելվածի համար
Կոնտեյներները դարձել են հավելվածները ծրագրային և օպերացիոն համակարգերի բոլոր կախվածություններով փաթեթավորելու և այնուհետև դրանք տարբեր միջավայրեր հասցնելու նախընտրելի միջոցը:
Այս հոդվածը ներառում է Spring Boot հավելվածի կոնտեյներացման տարբեր եղանակներ.
Docker ֆայլի միջոցով ստեղծելով Docker պատկեր,
ստեղծելով OCI պատկեր աղբյուրից՝ օգտագործելով Cloud-Native Buildpack,
և գործարկման ժամանակի պատկերի օպտիմիզացում՝ JAR-ի մասերը տարբեր շերտերի բաժանելով՝ օգտագործելով բազմաշերտ գործիքներ:
Կոդի օրինակ
Այս հոդվածը կցվում է աշխատանքային կոդի օրինակով GitHub-ում .
Կոնտեյների տերմինաբանություն
Մենք կսկսենք հոդվածում օգտագործված կոնտեյների տերմինաբանությունից.
Կոնտեյների պատկեր: որոշակի ձևաչափի ֆայլ: Մենք մեր հավելվածը կվերածենք կոնտեյների պատկերի` գործարկելով build գործիքը:
ԲեռնարկղԿոնտեյների պատկերի գործարկվող օրինակ:
Բեռնարկղային շարժիչԴեյմոն գործընթաց, որը պատասխանատու է կոնտեյների գործարկման համար:
Կոնտեյների հյուրընկալողՀյուրընկալող համակարգիչ, որի վրա աշխատում է կոնտեյների շարժիչը:
Կոնտեյների ռեեստրԸնդհանուր տեղադրությունը, որն օգտագործվում է կոնտեյների պատկերը հրապարակելու և տարածելու համար:
OCI ստանդարտ: Open Container Initiative (OCI) թեթև, բաց կառավարման կառույց է, որը ձևավորվել է Linux հիմնադրամի շրջանակներում: OCI Image Specification-ը սահմանում է արդյունաբերական ստանդարտներ կոնտեյների պատկերի և գործարկման ժամանակի ձևաչափերի համար՝ ապահովելու համար, որ բոլոր կոնտեյների շարժիչները կարող են գործարկել կոնտեյների պատկերները, որոնք ստեղծված են ցանկացած կառուցման գործիքի միջոցով:
Հավելվածը կոնտեյներացնելու համար մենք մեր հավելվածը փաթաթում ենք կոնտեյների պատկերով և հրապարակում այդ պատկերը ընդհանուր ռեեստրում: Կոնտեյների գործարկման ժամանակը վերցնում է այս պատկերը ռեեստրից, ապափաթեթավորում է այն և գործարկում հավելվածը դրա ներսում:
Spring Boot-ի 2.3 տարբերակը տրամադրում է պլագիններ OCI պատկերներ ստեղծելու համար:
դոկեր Սա ամենահաճախ օգտագործվող կոնտեյների իրականացումն է, և մենք օգտագործում ենք Docker-ը մեր օրինակներում, ուստի այս հոդվածի բոլոր հետագա կոնտեյների հղումները վերաբերելու են Docker-ին:
Կոնտեյների պատկերի կառուցում ավանդական եղանակով
Spring Boot հավելվածների համար Docker պատկերների ստեղծումը շատ հեշտ է՝ մի քանի հրահանգներ ավելացնելով Docker ֆայլին:
Մենք նախ ստեղծում ենք գործարկվող JAR ֆայլ և որպես Docker ֆայլի հրահանգների մաս, անհրաժեշտ կարգավորումները կիրառելուց հետո պատճենում ենք գործարկվող JAR ֆայլը բազային JRE պատկերի վերևում:
Եկեք ստեղծենք մեր Գարուն հավելվածը Spring Initializr կախվածությունների հետ web, lombokи actuator. Մենք նաև ավելացնում ենք հանգստի կարգավորիչ՝ API տրամադրելու համար GETմեթոդ.
Dockerfile-ի ստեղծում
Մենք այնուհետև կոնտեյներային ենք դարձնում այս հավելվածը՝ ավելացնելով Dockerfile:
Մեր 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 հրամանի արդյունքի մի մասը.
Ինչպես տեսնում ենք, կիրառական շերտը կազմում է պատկերի չափի զգալի մասը: Մենք ցանկանում ենք նվազեցնել այս շերտի չափը հետևյալ բաժիններում՝ որպես մեր օպտիմալացման մաս:
Buildpack-ի միջոցով կոնտեյների պատկերի ստեղծում
Մոնտաժային փաթեթներ (Buildpacks) ընդհանուր տերմին է, որն օգտագործվում է տարբեր Պլատֆորմ որպես ծառայություն (PAAS) առաջարկների կողմից՝ աղբյուրի կոդից կոնտեյների պատկեր ստեղծելու համար: Այն գործարկվել է Heroku-ի կողմից 2011 թվականին և այնուհետև ընդունվել է Cloud Foundry-ի, Google App Engine-ի, Gitlab-ի, Knative-ի և մի քանի այլ կողմից:
Ամպային կառուցման փաթեթների առավելությունները
Պատկերներ ստեղծելու համար Buildpack-ի օգտագործման հիմնական առավելություններից մեկն այն է Պատկերի կազմաձևման փոփոխությունները կարող են կառավարվել կենտրոնական (շինարար) և տարածվել բոլոր հավելվածներում՝ օգտագործելով Builder:
Կառուցման փաթեթները սերտորեն կապված էին հարթակի հետ: Cloud-Native Buildpacks-ը ապահովում է ստանդարտացում բոլոր հարթակներում՝ աջակցելով OCI պատկերի ձևաչափին, որն ապահովում է, որ պատկերը կարող է գործարկվել Docker շարժիչով:
Օգտագործելով Spring Boot հավելվածը
Spring Boot plugin-ը կառուցում է OCI պատկերներ աղբյուրից՝ օգտագործելով Buildpack: Պատկերները ստեղծվում են օգտագործելով bootBuildImageառաջադրանքներ (Gradle) կամ spring-boot:build-imageթիրախներ (Maven) և տեղական Docker տեղադրում:
Մենք կարող ենք հարմարեցնել պատկերի անունը, որն անհրաժեշտ է Docker ռեգիստր մղելու համար՝ նշելով անունը image tag:
Եկեք օգտագործենք Maven-ը դա անելու համար build-imageհավելված ստեղծելու և կոնտեյների պատկեր ստեղծելու նպատակները: Մենք այս պահին ոչ մի Dockerfiles չենք օգտագործում:
Արդյունքից մենք տեսնում ենք, որ paketo Cloud-Native buildpackօգտագործվում է աշխատանքային OCI պատկեր ստեղծելու համար: Ինչպես նախկինում, մենք կարող ենք տեսնել պատկերը, որը նշված է որպես Docker պատկեր՝ գործարկելով հրամանը.
Հաջորդը, մենք գործարկում ենք Jib plugin-ը, օգտագործելով Maven հրամանը՝ հավելվածը ստեղծելու և կոնտեյների պատկեր ստեղծելու համար: Ինչպես նախկինում, մենք այստեղ չենք օգտագործում Docker ֆայլեր.
Վերոնշյալ 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 հավելվածի համար:
Օպտիմիզացված կոնտեյների պատկերի ստեղծում Spring Boot հավելվածի համար՝ օգտագործելով Buildpack
Spring Boot 2.3-ն աջակցում է շերտավորմանը՝ հաստ JAR ֆայլի մասերը հանելով առանձին շերտերի մեջ: Շերտավորման հատկությունը լռելյայն անջատված է և պետք է հստակորեն միացված լինի Spring Boot Maven հավելվածի միջոցով.
Մենք կօգտագործենք այս կոնֆիգուրացիան, որպեսզի կառուցենք մեր կոնտեյների պատկերը նախ Buildpack-ով, իսկ հետո Docker-ի հետ հետևյալ բաժիններում:
Եկեք գործարկենք build-imageMaven թիրախը կոնտեյների պատկեր ստեղծելու համար.
mvn spring-boot:build-image
Եթե մենք գործարկենք Dive-ը, որպեսզի տեսնենք շերտերը ստացված պատկերում, մենք կարող ենք տեսնել, որ կիրառական շերտը (կարմիրով ուրվագծված) շատ ավելի փոքր է կիլոբայթային տիրույթում, համեմատած այն, ինչ մենք ստացել ենք հաստ JAR ձևաչափով.
Օպտիմիզացված կոնտեյների պատկերի ստեղծում Spring Boot հավելվածի համար Docker-ի միջոցով
Maven կամ Gradle պլագին օգտագործելու փոխարեն մենք կարող ենք նաև Docker ֆայլով ստեղծել շերտավորված Docker JAR պատկեր։
Երբ մենք օգտագործում ենք Docker, մենք պետք է կատարենք երկու լրացուցիչ քայլ՝ շերտերը հանելու և դրանք վերջնական պատկերում պատճենելու համար:
Ստացված JAR-ի բովանդակությունը Maven-ն օգտագործելով՝ միացված շերտավորումով կառուցելուց հետո կունենա հետևյալ տեսքը.
Արդյունքը ցույց է տալիս լրացուցիչ JAR անունով spring-boot-jarmode-layertoolsи layersfle.idxֆայլ։ Այս լրացուցիչ JAR ֆայլը ապահովում է շերտավոր մշակման հնարավորություններ, ինչպես նկարագրված է հաջորդ բաժնում:
Առանձին շերտերից կախվածությունների արդյունահանում
Մեր շերտավորված JAR-ից շերտեր դիտելու և հանելու համար մենք օգտագործում ենք համակարգի հատկությունը -Djarmode=layertoolsսկզբի համար spring-boot-jarmode-layertoolsJAR հավելվածի փոխարեն.
Այս հրամանի գործարկումը արտադրում է ելք, որը պարունակում է առկա հրամանների տարբերակները.
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
Արդյունքը ցույց է տալիս հրամանները list, extractи helpс helpլինել լռելյայն: Եկեք գործարկենք հրամանը listտարբերակ:
java -Djarmode=layertools -jar target/usersignup-0.0.1-SNAPSHOT.jar list
Մենք տեսնում ենք կախվածությունների ցանկ, որոնք կարող են ավելացվել որպես շերտեր:
Կանխադրված շերտեր.
Շերտի անվանումը
Պարունակություն
dependencies
ցանկացած կախվածություն, որի տարբերակը չի պարունակում SNAPSHOT
spring-boot-loader
JAR Loader դասեր
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 ԿԲ է, և կախվածությունները պահվում են առանձին շերտերում:
Առանձին շերտերից ներքին կախվածությունների արդյունահանում
Մենք կարող ենք էլ ավելի նվազեցնել հավելվածի մակարդակի չափը՝ հանելով մեր սովորական կախվածություններից որևէ մեկը առանձին մակարդակի մեջ՝ դրանք հավելվածով փաթեթավորելու փոխարեն՝ դրանք հայտարարելով ymlնմանատիպ ֆայլ անունով layers.idx:
Այս ֆայլում layers.idxմենք ավելացրել ենք մաքսային կախվածություն անունով, io.myorgպարունակող կազմակերպության կախվածությունները՝ վերցված ընդհանուր պահոցից:
Արտադրողականություն
Այս հոդվածում մենք նայեցինք Cloud-Native Buildpacks-ի օգտագործմանը՝ կոնտեյների պատկեր ստեղծելու համար անմիջապես աղբյուրի կոդից: Սա սովորական եղանակով կոնտեյների պատկեր ստեղծելու համար Docker-ի օգտագործման այլընտրանքն է՝ նախ ստեղծել հաստ գործարկվող JAR ֆայլ, այնուհետև փաթեթավորել այն կոնտեյների պատկերի մեջ՝ նշելով Docker ֆայլի հրահանգները:
Մենք նաև դիտարկել ենք մեր կոնտեյների օպտիմալացումը՝ հնարավորություն տալով շերտավորման գործառույթը, որը կախվածությունը քաշում է առանձին շերտերի մեջ, որոնք պահվում են հոսթի վրա, և հավելվածի բարակ շերտը բեռնվում է բեռնարկղի կատարման շարժիչներում պլանավորման ժամանակ:
Հոդվածում օգտագործված բոլոր սկզբնաղբյուրները կարող եք գտնել այստեղ Github .
Հրամանի հղում
Ահա հրամանների արագ ամփոփումը, որոնք մենք օգտագործել ենք այս հոդվածում:
Համատեքստի մաքրում.
docker system prune -a
Դոկեր ֆայլի միջոցով կոնտեյների պատկեր ստեղծելը.
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-ում.