Berî ku taybetmendiyek têkeve hilberînê, di van rojên orkestratorên tevlihev û CI/CD de, rêyek dirêj heye ku ji peywirê berbi ceribandin û radestkirinê ve biçin. Berê, we dikaribû pelên nû bi navgîniya FTP-ê barkirin (êdî kes wiya nake, rast?), û pêvajoya "dakêşandinê" çirkeyan girt. Naha hûn hewce ne ku daxwaznameyek hevgirtinê biafirînin û demek dirêj li bendê bin ku taybetmendî bigihîje bikarhêneran.
Beşek vê rêyê avakirina wêneyek Docker e. Carinan civîn bi deqeyan, carinan jî bi deh deqeyan didomîne, ku bi zorê mirov dikare bibêje normal. Di vê gotarê de, em ê serîlêdanek hêsan a ku em ê di wêneyekê de pak bikin, çend rêbazan bicîh bînin da ku avahîsaziyê zûtir bikin, û li hûrgelên van rêbazan çawa dixebitin binihêrin.
Di afirandina û piştgirîkirina malperên medyayê de ezmûnek me ya baş heye:
Em li GitLab belav dikin. Em wêneyan berhev dikin, wan dişoxilînin GitLab Registry û wan derdixin hilberînê. Di vê navnîşê de tiştê herî dirêj komkirina wêneyan e. Mînakî: bêyî xweşbîniyê, her avakirina paşverû 14 hûrdem girt.
Di dawiyê de, eşkere bû ku em nema dikarin bi vî rengî bijîn, û em rûniştin ku em bizanin ka çima berhevkirina wêneyan ewqas dirêj dikişîne. Wekî encamek, me karî ku dema civînê dakêşin 30 çirkeyan!
Ji bo vê gotarê, ji bo ku bi hawîrdora Reminder-ê ve neyê girêdan, em li mînakek komkirina serîlêdana Angular a vala binêrin. Ji ber vê yekê, em serlêdana xwe biafirînin:
ng n app
PWA lê zêde bikin (em pêşverû ne):
ng add @angular/pwa --project app
Dema ku mîlyonek pakêtên npm têne dakêşandin, bila em fêr bibin ka wêneya docker çawa dixebite. Docker şiyana pakkirina serîlêdanan peyda dike û wan di hawîrdorek veqetandî de ku jê re tê gotin konteynir tê meşandin peyda dike. Bi saya veqetandinê, hûn dikarin gelek konteyneran bi hevdemî li ser yek serverê bimeşînin. Konteyniran ji makîneyên virtual pir siviktir in ji ber ku ew rasterast li ser kernelê pergalê dixebitin. Ji bo ku em konteynirek bi serîlêdana xwe re bimeşînin, pêşî hewce ye ku em wêneyek çêbikin ku tê de em ê her tiştê ku ji bo xebitandina serlêdana me hewce dike pak bikin. Bi bingehîn, wêneyek kopiyek pergala pelê ye. Mînakî, Dockerfile bigirin:
FROM node:12.16.2
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build --prod
Dockerfile komek rêwerzan e; Bi kirina her yek ji wan, Docker dê guheztinên pergala pelan hilîne û wan li ser yên berê bigire. Her tîm qatek xwe diafirîne. Û wêneyê qediyayî qat bi hev re têne hev kirin.
Ya ku girîng e ku hûn zanibin: her qatek Docker dikare cache bike. Ger ji avakirina paşîn ve tiştek neguherî, wê hingê li şûna ku emrê bicîh bîne, docker dê qatek amade hilde. Ji ber ku zêdebûna sereke ya leza çêkirinê dê ji ber karanîna cache be, dema pîvandina leza çêkirinê em ê bi taybetî bala xwe bidin avakirina wêneyek bi cache-ya amade. Ji ber vê yekê, gav bi gav:
- Em wêneyan bi herêmî jêbirin da ku rêveçûna berê bandorê li ceribandinê neke.
docker rmi $(docker images -q)
- Em cara yekem dest bi avakirinê dikin.
time docker build -t app .
- Em pelê src/index.html diguherînin - em karê bernamesazek teqlîd dikin.
- Em avakirina cara duyemîn dimeşînin.
time docker build -t app .
Ger hawîrdora avakirina wêneyan rast were mîheng kirin (bêtir li ser ya li jêr), wê hingê gava ku çêkirin dest pê dike, Docker dê jixwe komek cache li ser gemiyê hebe. Erka me ev e ku em fêr bibin ka meriv çawa cache bikar tîne da ku avahî bi lez bimeşe. Ji ber ku em texmîn dikin ku xebitandina avahîsaziyek bêyî cache tenê carekê diqewime -cara yekem- ji ber vê yekê em dikarin guh nedin wê gava yekem çiqas hêdî bû. Di ceribandinan de, xebata duyemîn a çêkirinê ji me re girîng e, gava ku kaş jixwe germ bûne û em amade ne ku kekê xwe bipêjin. Lêbelê, hin serişteyan dê li ser avakirina yekem jî bandor bikin.
Ka em Dockerfile ku li jor hatî destnîşan kirin têxin peldanka projeyê û dest bi avakirinê bikin. Hemî navnîşan ji bo hêsankirina xwendinê hatine berhev kirin.
$ 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
Em naveroka src/index.html diguherînin û cara duyemîn dimeşînin.
$ 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
Ji bo ku em bibînin ka wêneyê me heye, fermanê bimeşînin docker images
:
REPOSITORY TAG IMAGE ID CREATED SIZE
app latest 79f335df92d3 About a minute ago 1.74GB
Berî avakirina, docker hemî pelan di çarçoveyek heyî de digire û wan dişîne daemonê xwe Sending build context to Docker daemon 409MB
. Çarçoveya avakirinê wekî argumana paşîn a fermana çêkirinê tê destnîşan kirin. Di doza me de, ev pelrêça heyî - ".", - û Docker her tiştê ku me di vê peldankê de heye dikişîne. 409 MB gelek e: em bifikirin ka meriv wê çawa rast bike.
Kêmkirina çarçoveyê
Ji bo kêmkirina çarçoveyê, du vebijark hene. An jî hemî pelên ku ji bo kombûnê hewce ne di peldankek cihêreng de bixin û çarçoweya dokerê li ser vê peldankê destnîşan bikin. Dibe ku ev her gav ne rehet be, ji ber vê yekê gengaz e ku meriv îstîsnayan diyar bike: tiştê ku divê neyê kişandin nav çarçoweyê. Ji bo kirina vê yekê, pelê .dockerignore têxin nav projeyê û destnîşan bikin ku ji bo çêkirinê ne hewce ye:
.git
/node_modules
û avakirina dîsa bimeşînin:
$ 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 KB ji 409 MB pir çêtir e. Me mezinahiya wêneyê jî ji 1.74 kêm kir 1.38 GB:
REPOSITORY TAG IMAGE ID CREATED SIZE
app latest 4942f010792a 3 minutes ago 1.38GB
Ka em hewl bidin ku mezinahiya wêneyê bêtir kêm bikin.
Em Alpine bikar tînin
Rêyek din ku meriv li ser mezinahiya wêneyê hilîne ev e ku meriv wêneyek dêûbavê piçûk bikar bîne. Wêneyê dêûbav ew wêne ye ku wêneyê me li ser bingeha wê hatî amadekirin. Tebeqeya jêrîn bi fermanê tête diyar kirin FROM
li Dockerfile. Di doza me de, em wêneyek Ubuntu-based ku jixwe nodejs sazkirî ye bikar tînin. Û giran dibe ...
$ docker images -a | grep node
node 12.16.2 406aa3abbc6c 17 minutes ago 916MB
... hema gigabyte. Hûn dikarin bi karanîna wêneyek ku li ser bingeha Alpine Linux-ê ve girêdayî ye, deng bi girîngî kêm bikin. Alpine Linuxek pir piçûk e. Wêneya dockerê ji bo nodejs-a ku li ser alpine ye tenê 88.5 MB giran e. Ji ber vê yekê em di xaniyan de wêneyê xwe yê zindî biguherînin:
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
Diviyabû me hin tiştên ku ji bo avakirina serîlêdanê hewce ne saz bikin. Erê, Angular bêyî Python ¯(°_o)/¯ ava nake
Lê mezinahiya wêneyê daket 150 MB:
REPOSITORY TAG IMAGE ID CREATED SIZE
app latest aa031edc315a 22 minutes ago 761MB
Em hê pêştir herin.
Civîna pirqonaxa
Ne her tiştê ku di wêneyê de ye ew e ku em di hilberînê de hewce ne.
$ 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
Bi alîkariya alîkariya docker run app ls -lah
me li gorî wêneya xwe konteynir derxist app
û fermana di wê de pêk anî ls -lah
, piştî ku konteynerê karê xwe qedand.
Di hilberînê de em tenê peldankek hewce ne dist
. Di vê rewşê de, pel bi rengek pêdivî ye ku li derve bêne dayîn. Hûn dikarin hin serverek HTTP li ser nodejs bimeşînin. Lê em ê hêsantir bikin. Gotinek rûsî ku çar tîpên wê "y" hene texmîn bikin. Rast! Ynzhynyksy. Ka em bi nginx re wêneyek bikişînin, peldankek tê de bixin dist
û mîhengek piçûk:
server {
listen 80 default_server;
server_name localhost;
charset utf-8;
root /app/dist;
location / {
try_files $uri $uri/ /index.html;
}
}
Avakirina pir-qonaxa dê ji me re bibe alîkar ku em van hemî bikin. Ka em Dockerfile xwe biguherînin:
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 .
Niha du talîmatên me hene FROM
di Dockerfile de, her yek ji wan pêngavek avakirina cûda dimeşîne. Me gazî yê yekem kir builder
, lê ji FROM ya paşîn dest pê dike, wêneya meya dawî dê were amadekirin. Pêngava paşîn ev e ku em hunera meclîsa me ya di gava berê de di wêneya paşîn de bi nginx re kopî bikin. Mezinahiya wêneyê pir kêm bûye:
REPOSITORY TAG IMAGE ID CREATED SIZE
app latest 2c6c5da07802 29 minutes ago 36MB
Ka em konteynerê bi wêneya xwe bimeşînin û pê ewle bibin ku her tişt dixebite:
docker run -p8080:80 app
Bi karanîna vebijarka -p8080:80, me porta 8080 li ser makîneya xweya mêvandar şand porta 80 di hundurê konteynera ku nginx lê dimeşe. Di gerokê de vekin
Kêmkirina mezinahiya wêneyê ji 1.74 GB ber 36 MB bi girîngî wextê ku ji bo radestkirina serlêdana we ji hilberînê re digire kêm dike. Lê em vegerin dema civînê.
$ 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
Guhertina rêzika qatan
Sê gavên me yên pêşîn hatin girtin (nîşan Using cache
). Di gava çaremîn de, hemî pelên projeyê têne kopî kirin û di gava pêncemîn de girêdayî têne saz kirin RUN npm ci
- bi qasî 47.338s. Ger ku ew pir kêm diguhezin çima girêdanan her car ji nû ve saz bikin? Ka em fêhm bikin ka çima ew nehatin girtin. Mesele ev e ku Docker dê qat bi qat kontrol bike da ku bibîne ka ferman û pelên pê re têkildar hatine guhertin. Di gava çaremîn de, em hemî pelên projeya xwe kopî dikin, û di nav wan de, bê guman, guhertin hene, ji ber vê yekê Docker ne tenê vê qatê ji cacheyê nagire, lê di heman demê de hemî yên paşîn jî! Ka em li Dockerfile hin guhertinên piçûk bikin.
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 .
Pêşî, package.json û package-lock.json têne kopî kirin, paşê ve girêdayî têne saz kirin, û tenê piştî wê tevahiya proje tê kopî kirin. Di encamê da:
$ 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
Li şûna 46 hûrdem 3 çirke - pir çêtir! Rêzkirina rast a qatan girîng e: Pêşî em tiştê ku nayê guheztin kopî dikin, dûv re çi kêm diguhere, û di dawiyê de çi pir caran diguhere.
Dûv re, çend peyvan li ser berhevkirina wêneyan di pergalên CI/CD de.
Bikaranîna wêneyên berê ji bo cache
Ger em ji bo çêkirinê cûreyek çareseriya SaaS bikar bînin, wê hingê dibe ku cacheya herêmî ya Docker paqij û nû be. Ji bo ku doker cîhek bide ku qatên pijyayî bigire, wêneya çêkirî ya berê bidin wî.
Werin em mînakek ji avakirina serlêdana xwe di Çalakiyên GitHub de bigirin. Em vê konfigurasyonê bikar tînin
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
Wêne di du hûrdem û 20 çirkeyan de tê berhev kirin û berbi Pakêtên GitHub ve tê avêtin:
Naha em werin çêkirinê biguherînin da ku cache li ser bingeha wêneyên çêkirî yên berê were bikar anîn:
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
Pêşî divê em ji we re vebêjin ka çima du ferman têne destpêkirin build
. Rastî ev e ku di meclîsek pirqonaxî de wêneya encam dê komek qat ji qonaxa paşîn be. Di vê rewşê de, qatên ji qatên berê dê di wêneyê de nebin. Ji ber vê yekê, dema ku wêneya paşîn a ji avahiyek berê bikar tîne, Docker dê nikaribe qatên amade bibîne da ku wêneyê bi nodejs (qonaxa çêker) ava bike. Ji bo çareserkirina vê pirsgirêkê, wêneyek navîn tê çêkirin $IMAGE_NAME-builder-stage
û ji pakêtên GitHub re tê kişandin da ku ew di avahiyek paşîn de wekî çavkaniyek cache were bikar anîn.
Tevahiya dema civînê daxist deqîqeyek û nîv. Ji bo kişandina wêneyên berê nîv deqîqe derbas dibe.
Pêşîmakirin
Rêbazek din a çareserkirina pirsgirêka cacheya paqij a Docker ev e ku hûn hin qatan biguhezînin nav Dockerfile din, wê ji hev cuda ava bikin, wê bixin nav Registry Container û wê wekî dêûbav bikar bînin.
Em wêneya xweya nodejs diafirînin da ku serîlêdanek Angular ava bikin. Di projeyê de Dockerfile.node biafirînin
FROM node:12.16.2-alpine3.11
RUN apk --no-cache --update --virtual build-dependencies add
python
make
g++
Em di Docker Hub de wêneyek giştî berhev dikin û dişoxilînin:
docker build -t exsmund/node-for-angular -f Dockerfile.node .
docker push exsmund/node-for-angular:latest
Naha di Dockerfile-ya xweya sereke de em wêneya qedandî bikar tînin:
FROM exsmund/node-for-angular:latest as builder
...
Di mînaka me de, dema çêkirinê kêm nebû, lê wêneyên pêş-avakirî dikarin bikêr bin heke we gelek projeyên we hebin û neçar bin ku di her yek ji wan de heman girêdanan saz bikin.
Me li gelek rêbazan ji bo bilezkirina avakirina wêneyên docker nihêrî. Heke hûn dixwazin ku bicîhkirin zû biçe, biceribînin ku di projeya xwe de vê bikar bînin:
- kêmkirina çarçoveyê;
- bikaranîna wêneyên bavê piçûk;
- civîna pirqonaxa;
- guheztina rêzika rêwerzan di Dockerfile de ji bo karanîna bikêrhatî ya cache;
- sazkirina cache di pergalên CI/CD de;
- çêkirina pêşîn a wêneyan.
Ez hêvî dikim ku mînak dê zelaltir bike ka Docker çawa dixebite, û hûn ê karibin bi awakî xweş vesazkirina xwe mîheng bikin. Ji bo lîstina bi mînakên ji gotarê re, depoyek hatiye çêkirin
Source: www.habr.com