Որոշ խորհուրդներ, թե ինչպես արագացնել Docker պատկերների կառուցումը: Օրինակ, մինչև 30 վայրկյան

Մինչև որևէ հատկանիշի արտադրության մեջ մտնելը, բարդ նվագախմբի և CI/CD-ի այս օրերին, պարտավորությունից մինչև փորձարկումներ և առաքում երկար ճանապարհ կա անցնելու: Նախկինում դուք կարող էիք նոր ֆայլեր վերբեռնել FTP-ի միջոցով (այլևս ոչ ոք դա չի անում, այնպես չէ՞), և «տեղակայման» գործընթացը տևում էր վայրկյաններ: Այժմ դուք պետք է ստեղծեք միաձուլման հարցում և երկար սպասեք, որպեսզի հնարավորությունը հասնի օգտատերերին:

Այս ճանապարհի մի մասը Docker պատկերի կառուցումն է: Երբեմն հավաքը տեւում է րոպեներ, երբեմն տասնյակ րոպեներ, ինչը դժվար թե կարելի է նորմալ անվանել։ Այս հոդվածում մենք կվերցնենք մի պարզ ծրագիր, որը մենք կփաթեթավորենք պատկերի մեջ, կկիրառենք մի քանի մեթոդներ՝ արագացնելու կառուցումը և կդիտարկենք այս մեթոդների աշխատանքի նրբությունները:

Որոշ խորհուրդներ, թե ինչպես արագացնել Docker պատկերների կառուցումը: Օրինակ, մինչև 30 վայրկյան

Մենք լավ փորձ ունենք մեդիա կայքեր ստեղծելու և աջակցելու գործում. ՏԱՍՍ, The Bell, «Նոր թերթ», Հանրապետություն… Ոչ վաղ անցյալում մենք ընդլայնեցինք մեր պորտֆոլիոն՝ թողարկելով արտադրանքի կայք Հիշեցում. Եվ մինչ նոր հնարավորություններ արագ ավելացվեցին և հին սխալները շտկվեցին, դանդաղ տեղակայումը դարձավ մեծ խնդիր:

Մենք տեղակայվում ենք GitLab-ում: Մենք հավաքում ենք պատկերներ, դրանք մղում GitLab Registry և դրանք թողարկում ենք արտադրության: Այս ցուցակի ամենաերկար բանը պատկերների հավաքումն է: Օրինակ՝ առանց օպտիմալացման, հետին պլանի յուրաքանչյուր կառուցումը տևեց 14 րոպե:

Որոշ խորհուրդներ, թե ինչպես արագացնել Docker պատկերների կառուցումը: Օրինակ, մինչև 30 վայրկյան

Ի վերջո, պարզ դարձավ, որ մենք այլևս չենք կարող այսպես ապրել, և մենք նստեցինք պարզելու, թե ինչու են նկարները այդքան երկար հավաքում: Արդյունքում մեզ հաջողվեց հավաքման ժամանակը կրճատել մինչև 30 վայրկյան:

Որոշ խորհուրդներ, թե ինչպես արագացնել Docker պատկերների կառուցումը: Օրինակ, մինչև 30 վայրկյան

Այս հոդվածի համար Reminder-ի միջավայրի հետ կապված չլինելու համար եկեք դիտենք դատարկ Angular հավելվածի հավաքման օրինակ։ Այսպիսով, եկեք ստեղծենք մեր հավելվածը.

ng n app

Դրան ավելացրեք PWA (մենք առաջադեմ ենք).

ng add @angular/pwa --project app

Մինչ մեկ միլիոն npm փաթեթներ են ներբեռնվում, եկեք պարզենք, թե ինչպես է աշխատում դոկերի պատկերը: Docker-ը հնարավորություն է տալիս փաթեթավորել հավելվածները և գործարկել դրանք մեկուսացված միջավայրում, որը կոչվում է կոնտեյներ: Մեկուսացման շնորհիվ դուք կարող եք միաժամանակ բազմաթիվ կոնտեյներներ գործարկել մեկ սերվերի վրա: Կոնտեյներները շատ ավելի թեթև են, քան վիրտուալ մեքենաները, քանի որ դրանք աշխատում են անմիջապես համակարգի միջուկի վրա: Մեր հավելվածով կոնտեյներ գործարկելու համար մենք նախ պետք է ստեղծենք պատկեր, որում կփաթեթավորենք այն ամենը, ինչ անհրաժեշտ է մեր հավելվածի գործարկման համար: Ըստ էության, պատկերը ֆայլային համակարգի պատճենն է: Օրինակ, վերցրեք Dockerfile-ը.

FROM node:12.16.2
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build --prod

Dockerfile-ը հրահանգների մի շարք է. Դրանցից յուրաքանչյուրն անելով՝ Docker-ը կպահի փոփոխությունները ֆայլային համակարգում և կվերածի դրանք նախորդների վրա։ Յուրաքանչյուր թիմ ստեղծում է իր շերտը: Իսկ պատրաստի պատկերը շերտերն են՝ համակցված միասին:

Ինչ կարևոր է իմանալ. Docker-ի յուրաքանչյուր շերտ կարող է քեշավորել: Եթե ​​վերջին կառուցումից հետո ոչինչ չի փոխվել, ապա հրամանը կատարելու փոխարեն դոկերը կվերցնի պատրաստի շերտ։ Քանի որ կառուցման արագության հիմնական աճը պայմանավորված է քեշի օգտագործմամբ, կառուցման արագությունը չափելիս մենք հատուկ ուշադրություն ենք դարձնելու պատրաստի քեշով պատկեր կառուցելուն: Այսպիսով, քայլ առ քայլ.

  1. Մենք ջնջում ենք պատկերները լոկալ, որպեսզի նախորդ գործարկումները չազդեն թեստի վրա:
    docker rmi $(docker images -q)
  2. Մենք առաջին անգամ ենք գործարկում շինարարությունը:
    time docker build -t app .
  3. Մենք փոխում ենք src/index.html ֆայլը - ընդօրինակում ենք ծրագրավորողի աշխատանքը։
  4. Մենք կառուցում ենք երկրորդ անգամ:
    time docker build -t app .

Եթե ​​պատկերների կառուցման միջավայրը ճիշտ կազմաձևված է (այդ մասին ավելին ստորև), ապա երբ կառուցումը սկսվի, Docker-ն արդեն կունենա մի փունջ քեշեր: Մեր խնդիրն է սովորել, թե ինչպես օգտագործել քեշը, որպեսզի կառուցումն անցնի հնարավորինս արագ: Քանի որ մենք ենթադրում ենք, որ առանց քեշի բիլդ գործարկելը տեղի է ունենում միայն մեկ անգամ՝ առաջին անգամ, հետևաբար կարող ենք անտեսել, թե որքան դանդաղ էր այդ առաջին անգամը: Թեստերում մեզ համար կարևոր է կառուցման երկրորդ գործարկումը, երբ քեշերն արդեն տաքացել են, և մենք պատրաստ ենք թխել մեր տորթը: Այնուամենայնիվ, որոշ խորհուրդներ նույնպես կազդեն առաջին կառուցման վրա:

Եկեք վերը նկարագրված Dockerfile-ը դնենք նախագծի թղթապանակում և սկսենք build-ը։ Բոլոր ցանկերը խտացվել են ընթերցանության հեշտության համար:

$ time docker build -t app .
Sending build context to Docker daemon 409MB
Step 1/5 : FROM node:12.16.2
Status: Downloaded newer image for node:12.16.2
Step 2/5 : WORKDIR /app
Step 3/5 : COPY . .
Step 4/5 : RUN npm ci
added 1357 packages in 22.47s
Step 5/5 : RUN npm run build --prod
Date: 2020-04-16T19:20:09.664Z - Hash: fffa0fddaa3425c55dd3 - Time: 37581ms
Successfully built c8c279335f46
Successfully tagged app:latest

real 5m4.541s
user 0m0.000s
sys 0m0.000s

Մենք փոխում ենք src/index.html-ի բովանդակությունը և գործարկում այն ​​երկրորդ անգամ:

$ time docker build -t app .
Sending build context to Docker daemon 409MB
Step 1/5 : FROM node:12.16.2
Step 2/5 : WORKDIR /app
 ---> Using cache
Step 3/5 : COPY . .
Step 4/5 : RUN npm ci
added 1357 packages in 22.47s
Step 5/5 : RUN npm run build --prod
Date: 2020-04-16T19:26:26.587Z - Hash: fffa0fddaa3425c55dd3 - Time: 37902ms
Successfully built 79f335df92d3
Successfully tagged app:latest

real 3m33.262s
user 0m0.000s
sys 0m0.000s

Տեսնելու համար, թե արդյոք ունենք պատկերը, գործարկեք հրամանը docker images:

REPOSITORY   TAG      IMAGE ID       CREATED              SIZE
app          latest   79f335df92d3   About a minute ago   1.74GB

Նախքան կառուցելը, docker-ը վերցնում է բոլոր ֆայլերը ընթացիկ համատեքստում և ուղարկում դրանք իր դեյմոնին Sending build context to Docker daemon 409MB. Կառուցման համատեքստը նշվում է որպես build հրամանի վերջին արգումենտ: Մեր դեպքում սա ընթացիկ գրացուցակն է՝ «.», - և Docker-ը քաշում է այն ամենը, ինչ մենք ունենք այս թղթապանակում: 409 ՄԲ-ը շատ է. եկեք մտածենք, թե ինչպես դա շտկել:

Համատեքստի կրճատում

Համատեքստը նվազեցնելու համար երկու տարբերակ կա. Կամ հավաքման համար անհրաժեշտ բոլոր ֆայլերը տեղադրեք առանձին թղթապանակում և ուղղեք դոկերի համատեքստը այս թղթապանակին: Սա միշտ չէ, որ հարմար է, ուստի կարելի է նշել բացառություններ՝ այն, ինչը չպետք է ներքաշվի համատեքստում: Դա անելու համար նախագծում տեղադրեք .dockerignore ֆայլը և նշեք, թե ինչն անհրաժեշտ չէ կառուցման համար.

.git
/node_modules

և նորից գործարկեք build-ը.

$ time docker build -t app .
Sending build context to Docker daemon 607.2kB
Step 1/5 : FROM node:12.16.2
Step 2/5 : WORKDIR /app
 ---> Using cache
Step 3/5 : COPY . .
Step 4/5 : RUN npm ci
added 1357 packages in 22.47s
Step 5/5 : RUN npm run build --prod
Date: 2020-04-16T19:33:54.338Z - Hash: fffa0fddaa3425c55dd3 - Time: 37313ms
Successfully built 4942f010792a
Successfully tagged app:latest

real 1m47.763s
user 0m0.000s
sys 0m0.000s

607.2 ԿԲ-ը շատ ավելի լավ է, քան 409 ՄԲ: Մենք նաև կրճատեցինք պատկերի չափը 1.74-ից մինչև 1.38 ԳԲ.

REPOSITORY   TAG      IMAGE ID       CREATED         SIZE
app          latest   4942f010792a   3 minutes ago   1.38GB

Փորձենք ավելի փոքրացնել պատկերի չափը։

Մենք օգտագործում ենք Alpine

Պատկերի չափը խնայելու մեկ այլ միջոց է օգտագործել փոքր ծնողի պատկերը: Ծնողների կերպարն այն կերպարն է, որի հիման վրա պատրաստվում է մեր կերպարը։ Ներքևի շերտը նշված է հրամանով FROM Dockerfile-ում։ Մեր դեպքում մենք օգտագործում ենք Ubuntu-ի վրա հիմնված պատկեր, որն արդեն ունի nodej-ներ տեղադրված: Եվ կշռում է...

$ docker images -a | grep node
node 12.16.2 406aa3abbc6c 17 minutes ago 916MB

... գրեթե մեկ գիգաբայթ: Դուք կարող եք զգալիորեն նվազեցնել ձայնի ծավալը՝ օգտագործելով Alpine Linux-ի վրա հիմնված պատկեր: Alpine-ը շատ փոքր Linux է: Alpine-ի վրա հիմնված nodejs-ի դոկերի պատկերը կշռում է ընդամենը 88.5 ՄԲ: Այսպիսով, եկեք փոխարինենք մեր աշխույժ կերպարը տներում.

FROM node:12.16.2-alpine3.11
RUN apk --no-cache --update --virtual build-dependencies add 
    python 
    make 
    g++
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build --prod

Մենք ստիպված էինք տեղադրել որոշ բաներ, որոնք անհրաժեշտ են հավելվածը ստեղծելու համար: Այո, Angular-ը չի կառուցում առանց Python ¯(°_o)/¯

Բայց պատկերի չափը իջավ մինչև 150 ՄԲ.

REPOSITORY   TAG      IMAGE ID       CREATED          SIZE
app          latest   aa031edc315a   22 minutes ago   761MB

Եկեք գնանք նույնիսկ ավելի հեռու:

Բազմաստիճան հավաքում

Այն ամենը, ինչ պատկերված է, այն չէ, ինչ մեզ անհրաժեշտ է արտադրության մեջ:

$ docker run app ls -lah
total 576K
drwxr-xr-x 1 root root 4.0K Apr 16 19:54 .
drwxr-xr-x 1 root root 4.0K Apr 16 20:00 ..
-rwxr-xr-x 1 root root 19 Apr 17 2020 .dockerignore
-rwxr-xr-x 1 root root 246 Apr 17 2020 .editorconfig
-rwxr-xr-x 1 root root 631 Apr 17 2020 .gitignore
-rwxr-xr-x 1 root root 181 Apr 17 2020 Dockerfile
-rwxr-xr-x 1 root root 1020 Apr 17 2020 README.md
-rwxr-xr-x 1 root root 3.6K Apr 17 2020 angular.json
-rwxr-xr-x 1 root root 429 Apr 17 2020 browserslist
drwxr-xr-x 3 root root 4.0K Apr 16 19:54 dist
drwxr-xr-x 3 root root 4.0K Apr 17 2020 e2e
-rwxr-xr-x 1 root root 1015 Apr 17 2020 karma.conf.js
-rwxr-xr-x 1 root root 620 Apr 17 2020 ngsw-config.json
drwxr-xr-x 1 root root 4.0K Apr 16 19:54 node_modules
-rwxr-xr-x 1 root root 494.9K Apr 17 2020 package-lock.json
-rwxr-xr-x 1 root root 1.3K Apr 17 2020 package.json
drwxr-xr-x 5 root root 4.0K Apr 17 2020 src
-rwxr-xr-x 1 root root 210 Apr 17 2020 tsconfig.app.json
-rwxr-xr-x 1 root root 489 Apr 17 2020 tsconfig.json
-rwxr-xr-x 1 root root 270 Apr 17 2020 tsconfig.spec.json
-rwxr-xr-x 1 root root 1.9K Apr 17 2020 tslint.json

Հետ docker run app ls -lah մենք գործարկեցինք կոնտեյներ՝ հիմնված մեր պատկերի վրա app և կատարեց հրամանը դրանում ls -lah, որից հետո տարան ավարտեց իր աշխատանքը։

Արտադրության մեջ մեզ անհրաժեշտ է միայն թղթապանակ dist. Այս դեպքում ֆայլերը ինչ-որ կերպ պետք է դրսում տրվեն։ Դուք կարող եք գործարկել որոշ HTTP սերվեր nodejs-ում: Բայց մենք կհեշտացնենք դա: Գուշակիր ռուսերեն բառը, որն ունի չորս «y» տառ: Ճիշտ! Ynzhynyksy. Արի nginx-ով նկար վերցնենք, մեջը թղթապանակ դնենք dist և մի փոքր կոնֆիգուր՝

server {
    listen 80 default_server;
    server_name localhost;
    charset utf-8;
    root /app/dist;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

Բազմաստիճան շինարարությունը կօգնի մեզ այս ամենն անել: Եկեք փոխենք մեր Dockerfile-ը.

FROM node:12.16.2-alpine3.11 as builder
RUN apk --no-cache --update --virtual build-dependencies add 
    python 
    make 
    g++
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build --prod

FROM nginx:1.17.10-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/static.conf /etc/nginx/conf.d
COPY --from=builder /app/dist/app .

Այժմ մենք ունենք երկու հրահանգ FROM Dockerfile-ում նրանցից յուրաքանչյուրը կատարում է տարբեր կառուցման քայլ: Առաջինին կանչեցինք builder, բայց սկսած վերջին FROM-ից կպատրաստվի մեր վերջնական պատկերը։ Վերջին քայլը նախորդ քայլի մեր հավաքի արտեֆակտը nginx-ով վերջնական պատկերի մեջ պատճենելն է: Պատկերի չափը զգալիորեն նվազել է.

REPOSITORY   TAG      IMAGE ID       CREATED          SIZE
app          latest   2c6c5da07802   29 minutes ago   36MB

Եկեք գործարկենք կոնտեյները մեր պատկերով և համոզվենք, որ ամեն ինչ աշխատում է.

docker run -p8080:80 app

Օգտագործելով -p8080:80 տարբերակը, մենք փոխանցեցինք 8080 նավահանգիստը մեր հյուրընկալող մեքենայի վրա դեպի 80 նավահանգիստ այն կոնտեյների ներսում, որտեղ աշխատում է nginx-ը: Բացեք բրաուզերում http://localhost:8080/ և մենք տեսնում ենք մեր դիմումը: Ամեն ինչ աշխատում է!

Որոշ խորհուրդներ, թե ինչպես արագացնել Docker պատկերների կառուցումը: Օրինակ, մինչև 30 վայրկյան

Պատկերի չափը 1.74 ԳԲ-ից մինչև 36 ՄԲ նվազեցնելը զգալիորեն նվազեցնում է ձեր հավելվածը արտադրությանը հասցնելու ժամանակը: Բայց եկեք վերադառնանք հավաքման ժամանակին:

$ time docker build -t app .
Sending build context to Docker daemon 608.8kB
Step 1/11 : FROM node:12.16.2-alpine3.11 as builder
Step 2/11 : RUN apk --no-cache --update --virtual build-dependencies add python make g++
 ---> Using cache
Step 3/11 : WORKDIR /app
 ---> Using cache
Step 4/11 : COPY . .
Step 5/11 : RUN npm ci
added 1357 packages in 47.338s
Step 6/11 : RUN npm run build --prod
Date: 2020-04-16T21:16:03.899Z - Hash: fffa0fddaa3425c55dd3 - Time: 39948ms
 ---> 27f1479221e4
Step 7/11 : FROM nginx:stable-alpine
Step 8/11 : WORKDIR /app
 ---> Using cache
Step 9/11 : RUN rm /etc/nginx/conf.d/default.conf
 ---> Using cache
Step 10/11 : COPY nginx/static.conf /etc/nginx/conf.d
 ---> Using cache
Step 11/11 : COPY --from=builder /app/dist/app .
Successfully built d201471c91ad
Successfully tagged app:latest

real 2m17.700s
user 0m0.000s
sys 0m0.000s

Շերտերի հերթականության փոփոխություն

Մեր առաջին երեք քայլերը պահվել են (ակնարկ Using cache) Չորրորդ քայլում բոլոր նախագծի ֆայլերը պատճենվում են, իսկ հինգերորդ քայլում տեղադրվում են կախվածությունները RUN npm ci - որքան 47.338 վրկ. Ինչու՞ ամեն անգամ նորից տեղադրել կախվածությունները, եթե դրանք շատ հազվադեպ են փոխվում: Եկեք պարզենք, թե ինչու դրանք չեն պահվել: Բանն այն է, որ Docker-ը շերտ առ շերտ կստուգի, թե արդյոք հրամանը և դրա հետ կապված ֆայլերը փոխվել են։ Չորրորդ քայլում մենք պատճենում ենք մեր նախագծի բոլոր ֆայլերը, և դրանց թվում, իհարկե, կան փոփոխություններ, այնպես որ Docker-ը ոչ միայն չի վերցնում այս շերտը քեշից, այլև բոլոր հաջորդները: Եկեք մի քանի փոքր փոփոխություններ կատարենք Dockerfile-ում:

FROM node:12.16.2-alpine3.11 as builder
RUN apk --no-cache --update --virtual build-dependencies add 
    python 
    make 
    g++
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build --prod

FROM nginx:1.17.10-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/static.conf /etc/nginx/conf.d
COPY --from=builder /app/dist/app .

Նախ պատճենվում են package.json-ը և package-lock.json-ը, այնուհետև տեղադրվում են կախվածությունները և միայն դրանից հետո պատճենվում է ամբողջ նախագիծը: Որպես արդյունք:

$ time docker build -t app .
Sending build context to Docker daemon 608.8kB
Step 1/12 : FROM node:12.16.2-alpine3.11 as builder
Step 2/12 : RUN apk --no-cache --update --virtual build-dependencies add python make g++
 ---> Using cache
Step 3/12 : WORKDIR /app
 ---> Using cache
Step 4/12 : COPY package*.json ./
 ---> Using cache
Step 5/12 : RUN npm ci
 ---> Using cache
Step 6/12 : COPY . .
Step 7/12 : RUN npm run build --prod
Date: 2020-04-16T21:29:44.770Z - Hash: fffa0fddaa3425c55dd3 - Time: 38287ms
 ---> 1b9448c73558
Step 8/12 : FROM nginx:stable-alpine
Step 9/12 : WORKDIR /app
 ---> Using cache
Step 10/12 : RUN rm /etc/nginx/conf.d/default.conf
 ---> Using cache
Step 11/12 : COPY nginx/static.conf /etc/nginx/conf.d
 ---> Using cache
Step 12/12 : COPY --from=builder /app/dist/app .
Successfully built a44dd7c217c3
Successfully tagged app:latest

real 0m46.497s
user 0m0.000s
sys 0m0.000s

46 վայրկյան 3 րոպեի փոխարեն՝ շատ ավելի լավ: Կարևոր է շերտերի ճիշտ դասավորությունը՝ նախ պատճենում ենք այն, ինչ չի փոխվում, հետո այն, ինչը հազվադեպ է փոխվում, և վերջում այն, ինչ հաճախ է փոխվում։

Հաջորդը, մի քանի խոսք CI/CD համակարգերում պատկերներ հավաքելու մասին:

Օգտագործելով նախորդ պատկերները քեշի համար

Եթե ​​կառուցման համար օգտագործենք ինչ-որ SaaS լուծում, ապա տեղական Docker քեշը կարող է մաքուր և թարմ լինել: Դոկերին թխած շերտերը ստանալու տեղ տալու համար տվեք նրան նախորդ կառուցված պատկերը։

Բերենք GitHub Actions-ում մեր հավելվածը կառուցելու օրինակ: Մենք օգտագործում ենք այս կազմաձևը

on:
  push:
    branches:
      - master

name: Test docker build

jobs:
  deploy:
    name: Build
    runs-on: ubuntu-latest
    env:
      IMAGE_NAME: docker.pkg.github.com/${{ github.repository }}/app
      IMAGE_TAG: ${{ github.sha }}

    steps:
    - name: Checkout
      uses: actions/checkout@v2

    - name: Login to GitHub Packages
      env:
        TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        docker login docker.pkg.github.com -u $GITHUB_ACTOR -p $TOKEN

    - name: Build
      run: |
        docker build 
          -t $IMAGE_NAME:$IMAGE_TAG 
          -t $IMAGE_NAME:latest 
          .

    - name: Push image to GitHub Packages
      run: |
        docker push $IMAGE_NAME:latest
        docker push $IMAGE_NAME:$IMAGE_TAG

    - name: Logout
      run: |
        docker logout docker.pkg.github.com

Պատկերը հավաքվում և ուղարկվում է GitHub փաթեթներ երկու րոպե 20 վայրկյանում.

Որոշ խորհուրդներ, թե ինչպես արագացնել Docker պատկերների կառուցումը: Օրինակ, մինչև 30 վայրկյան

Հիմա եկեք փոխենք կառուցվածքը այնպես, որ քեշը օգտագործվի՝ հիմնվելով նախկինում կառուցված պատկերների վրա.

on:
  push:
    branches:
      - master

name: Test docker build

jobs:
  deploy:
    name: Build
    runs-on: ubuntu-latest
    env:
      IMAGE_NAME: docker.pkg.github.com/${{ github.repository }}/app
      IMAGE_TAG: ${{ github.sha }}

    steps:
    - name: Checkout
      uses: actions/checkout@v2

    - name: Login to GitHub Packages
      env:
        TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        docker login docker.pkg.github.com -u $GITHUB_ACTOR -p $TOKEN

    - name: Pull latest images
      run: |
        docker pull $IMAGE_NAME:latest || true
        docker pull $IMAGE_NAME-builder-stage:latest || true

    - name: Images list
      run: |
        docker images

    - name: Build
      run: |
        docker build 
          --target builder 
          --cache-from $IMAGE_NAME-builder-stage:latest 
          -t $IMAGE_NAME-builder-stage 
          .
        docker build 
          --cache-from $IMAGE_NAME-builder-stage:latest 
          --cache-from $IMAGE_NAME:latest 
          -t $IMAGE_NAME:$IMAGE_TAG 
          -t $IMAGE_NAME:latest 
          .

    - name: Push image to GitHub Packages
      run: |
        docker push $IMAGE_NAME-builder-stage:latest
        docker push $IMAGE_NAME:latest
        docker push $IMAGE_NAME:$IMAGE_TAG

    - name: Logout
      run: |
        docker logout docker.pkg.github.com

Նախ պետք է պատմենք, թե ինչու են գործարկվում երկու հրամաններ build. Փաստն այն է, որ բազմաստիճան ժողովում ստացված պատկերը կլինի վերջին փուլի շերտերի մի շարք: Այս դեպքում նախորդ շերտերի շերտերը չեն ներառվի նկարում: Հետևաբար, նախորդ կառուցման վերջնական պատկերն օգտագործելիս Docker-ը չի կարողանա գտնել պատրաստի շերտեր՝ պատկերը nodejs-ով (շինարարական փուլ) կառուցելու համար։ Այս խնդիրը լուծելու համար ստեղծվում է միջանկյալ պատկեր $IMAGE_NAME-builder-stage և մղվում է դեպի GitHub փաթեթներ, որպեսզի այն կարողանա օգտագործվել հետագա կառուցման մեջ՝ որպես քեշի աղբյուր:

Որոշ խորհուրդներ, թե ինչպես արագացնել Docker պատկերների կառուցումը: Օրինակ, մինչև 30 վայրկյան

Հավաքման ընդհանուր ժամանակը կրճատվել է մինչև մեկուկես րոպե: Կես րոպե ծախսվում է նախորդ նկարները վեր հանելու համար:

Նախնական պատկերացում

Մաքուր Docker քեշի խնդիրը լուծելու մեկ այլ միջոց է շերտերից մի քանիսը տեղափոխել մեկ այլ Dockerfile, կառուցել այն առանձին, մղել այն Container Registry և օգտագործել այն որպես ծնող:

Մենք ստեղծում ենք մեր սեփական nodejs պատկերը՝ Angular հավելված ստեղծելու համար: Նախագծում ստեղծեք Dockerfile.node

FROM node:12.16.2-alpine3.11
RUN apk --no-cache --update --virtual build-dependencies add 
    python 
    make 
    g++

Մենք հավաքում և հրում ենք հանրային պատկեր Docker Hub-ում.

docker build -t exsmund/node-for-angular -f Dockerfile.node .
docker push exsmund/node-for-angular:latest

Այժմ մեր հիմնական Dockerfile-ում մենք օգտագործում ենք պատրաստի պատկերը.

FROM exsmund/node-for-angular:latest as builder
...

Մեր օրինակում կառուցման ժամանակը չի նվազել, բայց նախապես կառուցված պատկերները կարող են օգտակար լինել, եթե դուք ունեք բազմաթիվ նախագծեր և պետք է տեղադրեք նույն կախվածությունները դրանցից յուրաքանչյուրում:

Որոշ խորհուրդներ, թե ինչպես արագացնել Docker պատկերների կառուցումը: Օրինակ, մինչև 30 վայրկյան

Մենք դիտարկեցինք մի քանի մեթոդներ՝ արագացնելու դոկերի պատկերների կառուցումը: Եթե ​​ցանկանում եք, որ տեղակայումն արագ անցնի, փորձեք օգտագործել սա ձեր նախագծում.

  • համատեքստի կրճատում;
  • փոքր ծնողական պատկերների օգտագործում;
  • բազմաստիճան հավաքում;
  • փոխելով Dockerfile-ում հրահանգների հերթականությունը՝ քեշը արդյունավետ օգտագործելու համար.
  • CI/CD համակարգերում քեշի տեղադրում;
  • պատկերների նախնական ստեղծում.

Հուսով եմ, որ օրինակն ավելի պարզ կդարձնի, թե ինչպես է աշխատում Docker-ը, և դուք կկարողանաք օպտիմալ կերպով կարգավորել ձեր տեղակայումը: Հոդվածի օրինակների հետ խաղալու համար ստեղծվել է շտեմարան https://github.com/devopsprodigy/test-docker-build.

Source: www.habr.com

Добавить комментарий