Sawetara tips babagan carane nyepetake nggawe gambar Docker. Contone, nganti 30 detik

Sadurunge fitur dadi produksi, ing jaman saiki orkestrator rumit lan CI / CD, ana cara sing dawa kanggo pindhah saka komitmen kanggo nyoba lan ngirim. Sadurunge, sampeyan bisa ngunggah file anyar liwat FTP (ora ana sing nindakake maneh, ta?), Lan proses "penyebaran" butuh sawetara detik. Saiki sampeyan kudu nggawe panjalukan gabungan lan ngenteni suwene fitur kasebut bisa tekan pangguna.

BagΓ©yan saka dalan iki mbangun gambar Docker. Kadhangkala perakitan kasebut nganti sawetara menit, kadhangkala puluhan menit, sing meh ora bisa diarani normal. Ing artikel iki, kita bakal njupuk aplikasi prasaja sing bakal kita bungkus dadi gambar, aplikasi sawetara cara kanggo nyepetake mbangun, lan ndeleng nuansa cara kerjane.

Sawetara tips babagan carane nyepetake nggawe gambar Docker. Contone, nganti 30 detik

Kita duwe pengalaman apik kanggo nggawe lan ndhukung situs web media: TASS, The Bell, "Koran Anyar", Republik… Ora suwe, kita ngembangake portofolio kanthi ngeculake situs web produk Pangeling. Lan nalika fitur-fitur anyar ditambahake kanthi cepet lan bug lawas didandani, penyebaran alon dadi masalah gedhe.

Kita nyebar menyang GitLab. Kita ngumpulake gambar, push menyang GitLab Registry lan gulung menyang produksi. Wangsulan: Bab ingkang paling dawa ing dhaftar iki assembling gambar. Contone: tanpa optimasi, saben mbangun backend njupuk 14 menit.

Sawetara tips babagan carane nyepetake nggawe gambar Docker. Contone, nganti 30 detik

Ing pungkasan, dadi cetha yen kita ora bisa urip maneh kaya iki, lan kita njagong mudhun kanggo mangerteni apa gambar njupuk supaya dawa kanggo ngumpulake. AkibatΓ©, kita bisa nyuda wektu perakitan dadi 30 detik!

Sawetara tips babagan carane nyepetake nggawe gambar Docker. Contone, nganti 30 detik

Kanggo artikel iki, supaya ora kaiket karo lingkungan Pangeling, ayo deleng conto ngumpulake aplikasi Angular sing kosong. Dadi, ayo nggawe aplikasi kita:

ng n app

Tambah PWA (kita progresif):

ng add @angular/pwa --project app

Nalika sejuta paket npm lagi diundhuh, ayo dipikirake kepiye cara kerjane gambar docker. Docker menehi kemampuan kanggo paket aplikasi lan mbukak ing lingkungan terisolasi disebut wadhah. Thanks kanggo isolasi, sampeyan bisa mbukak akeh kontaner bebarengan ing siji server. Kontainer luwih entheng tinimbang mesin virtual amarga langsung mbukak ing kernel sistem. Kanggo mbukak wadhah karo aplikasi kita, kita kudu nggawe gambar sing bakal ngemas kabeh sing dibutuhake supaya aplikasi bisa mlaku. Ateges, gambar minangka salinan sistem file. Contone, njupuk Dockerfile:

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

A Dockerfile minangka set instruksi; Kanthi nindakake saben wong, Docker bakal nyimpen owah-owahan ing sistem file lan overlay ing sing sadurunge. Saben tim nggawe lapisan dhewe. Lan gambar rampung lapisan digabungake bebarengan.

Sing penting kanggo ngerti: saben lapisan Docker bisa cache. Yen ora ana owah-owahan wiwit mbangun pungkasan, tinimbang nglakokake perintah kasebut, docker bakal njupuk lapisan sing wis siap. Wiwit kenaikan utama kacepetan mbangun bakal amarga nggunakake cache, nalika ngukur kacepetan mbangun kita bakal menehi perhatian khusus kanggo mbangun gambar kanthi cache sing wis siap. Dadi, langkah demi langkah:

  1. Kita mbusak gambar sacara lokal supaya sadurunge mlaku ora mengaruhi tes.
    docker rmi $(docker images -q)
  2. Kita miwiti mbangun kanggo pisanan.
    time docker build -t app .
  3. Kita ngganti file src/index.html - kita niru karya programmer.
  4. Kita mbukak mbangun kaping pindho.
    time docker build -t app .

Yen lingkungan kanggo mbangun gambar dikonfigurasi kanthi bener (liyane ing ngisor iki), banjur nalika mbangun diwiwiti, Docker bakal duwe akeh cache ing papan. Tugas kita yaiku sinau carane nggunakake cache supaya mbangun dadi cepet sabisa. Amarga kita nganggep manawa mbangun bangunan tanpa cache mung kedadeyan sapisan - sepisanan - mula kita bisa nglirwakake sepira alon banget. Ing tes, roto kapindho mbangun penting kanggo kita, nalika caches wis digawe panas lan kita siap kanggo panggangan jajan. Nanging, sawetara tips uga bakal mengaruhi mbangun pisanan.

Ayo sijine Dockerfile sing diterangake ing ndhuwur ing folder proyek lan miwiti mbangun. Kabeh dhaptar wis dipadhetke supaya gampang diwaca.

$ 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

Kita ngganti isi src/index.html lan mbukak kaping pindho.

$ 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

Kanggo ndeleng yen kita duwe gambar, jalanake printah kasebut docker images:

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

Sadurunge mbangun, docker njupuk kabeh file ing konteks saiki lan dikirim menyang daemon Sending build context to Docker daemon 409MB. Konteks mbangun ditemtokake minangka argumen pungkasan kanggo perintah mbangun. Ing kasus kita, iki minangka direktori saiki - ".", - lan Docker nyeret kabeh sing ana ing folder iki. 409 MB akeh banget: ayo dipikirake carane ndandani.

Ngurangi konteks

Kanggo nyuda konteks, ana rong pilihan. Utawa lebokake kabeh file sing dibutuhake kanggo perakitan ing folder sing kapisah lan arahake konteks docker menyang folder iki. Iki bisa uga ora mesthi trep, saengga bisa nemtokake pangecualian: apa sing ora kudu diseret menyang konteks. Kanggo nindakake iki, sijine file .dockerignore ing project lan nunjukakΓ© apa ora perlu kanggo mbangun:

.git
/node_modules

lan mbukak mbangun maneh:

$ 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 luwih apik tinimbang 409 MB. Kita uga nyuda ukuran gambar saka 1.74 dadi 1.38 GB:

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

Ayo dadi nyoba kanggo nyuda ukuran gambar luwih.

Kita nggunakake Alpine

Cara liya kanggo ngirit ukuran gambar yaiku nggunakake gambar induk cilik. Gambar wong tuwa yaiku gambar sing adhedhasar gambar kita disiapake. Lapisan ngisor ditemtokake dening printah FROM ing Dockerfile. Ing kasus kita, kita nggunakake gambar berbasis Ubuntu sing wis diinstal nodejs. Lan bobote ...

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

... meh gigabyte. Sampeyan bisa nyuda volume kanthi nyata kanthi nggunakake gambar adhedhasar Alpine Linux. Alpine minangka Linux sing cilik banget. Gambar docker kanggo nodej adhedhasar alpine bobote mung 88.5 MB. Dadi ayo ngganti gambar sing urip ing omah:

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

Kita kudu nginstal sawetara perkara sing perlu kanggo mbangun aplikasi kasebut. Ya, Angular ora mbangun tanpa Python Β―(Β°_o)/Β―

Nanging ukuran gambar mudhun dadi 150 MB:

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

Ayo luwih maju.

Multistage perakitan

Ora kabeh sing ana ing gambar iku sing dibutuhake ing produksi.

$ 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

Kanthi bantuan saka docker run app ls -lah kita mbukak wadhah adhedhasar gambar kita app lan kaleksanan printah ing ls -lah, sawise iku wadhah rampung karya.

Ing produksi kita mung butuh folder dist. Ing kasus iki, file kudu diwenehi ing njaba. Sampeyan bisa mbukak sawetara server HTTP ing nodejs. Nanging kita bakal nggawe luwih gampang. Tebak tembung Rusia sing duwe papat huruf "y". Bener! Ynzhynyksy. Ayo njupuk gambar karo nginx, sijine folder ing dist lan konfigurasi cilik:

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

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

Mbangun multi-tataran bakal mbantu kita nindakake kabeh iki. Ayo ngganti file Docker kita:

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 .

Saiki kita duwe rong instruksi FROM ing Dockerfile, saben wong nganggo langkah mbangun sing beda. Kita nelpon sing pisanan builder, nanging wiwit saka pungkasan FROM, gambar final kita bakal disiapake. Langkah pungkasan yaiku nyalin artefak perakitan kita ing langkah sadurunge menyang gambar pungkasan nganggo nginx. Ukuran gambar wis suda sacara signifikan:

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

Ayo mbukak wadhah nganggo gambar kita lan priksa manawa kabeh bisa digunakake:

docker run -p8080:80 app

Nggunakake opsi -p8080:80, kita nerusake port 8080 ing mesin host menyang port 80 ing njero wadhah ing ngendi nginx mlaku. Bukak ing browser http://localhost:8080/ lan kita ndeleng aplikasi kita. Kabeh mlaku!

Sawetara tips babagan carane nyepetake nggawe gambar Docker. Contone, nganti 30 detik

Ngurangi ukuran gambar saka 1.74 GB dadi 36 MB nyuda wektu sing dibutuhake kanggo ngirim aplikasi menyang produksi. Nanging ayo bali menyang wektu perakitan.

$ 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

Ngganti urutan lapisan

Telung langkah pisanan kita di-cache (petunjuk Using cache). Ing langkah kaping papat, kabeh file proyek disalin lan ing dependensi langkah kaping lima wis diinstal RUN npm ci - minangka akeh minangka 47.338s. Napa instal maneh dependensi yen arang banget diganti? Ayo ngerteni kenapa dheweke ora di-cache. Intine yaiku Docker bakal mriksa lapisan demi lapisan kanggo ndeleng apa perintah lan file sing ana gandhengane wis diganti. Ing langkah kaping papat, kita nyalin kabeh file proyek kita, lan ing antarane, mesthi ana owah-owahan, saengga Docker ora mung njupuk lapisan iki saka cache, nanging uga kabeh sing sabanjure! Ayo nggawe sawetara owah-owahan cilik menyang 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 .

Pisanan, package.json lan package-lock.json disalin, banjur dependensi diinstal, lan mung sawise kabeh proyek disalin. AkibatΓ©:

$ 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 detik tinimbang 3 menit - luwih apik! Urutan lapisan sing bener penting: pisanan kita nyalin apa sing ora owah, banjur apa sing jarang diganti, lan pungkasane apa sing kerep diganti.

Sabanjure, sawetara tembung babagan ngrakit gambar ing sistem CI / CD.

Nggunakake gambar sadurunge kanggo cache

Yen kita nggunakake sawetara jinis solusi SaaS kanggo mbangun, banjur cache Docker lokal bisa resik lan seger. Kanggo menehi docker panggonan kanggo njaluk lapisan panggang, menehi wong gambar dibangun sadurungΓ©.

Ayo njupuk conto nggawe aplikasi kita ing Tindakan GitHub. Kita nggunakake konfigurasi iki

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

Gambar kasebut dirakit lan di-push menyang Paket GitHub sajrone rong menit lan 20 detik:

Sawetara tips babagan carane nyepetake nggawe gambar Docker. Contone, nganti 30 detik

Saiki ayo ngganti mbangun supaya cache digunakake adhedhasar gambar sing dibangun sadurunge:

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

Kaping pisanan, kita kudu menehi pitutur marang kowe kenapa rong perintah diluncurake build. Kasunyatane yaiku ing perakitan multistage gambar sing diasilake bakal dadi set lapisan saka tahap pungkasan. Ing kasus iki, lapisan saka lapisan sadurunge ora bakal kalebu ing gambar. Mulane, nalika nggunakake gambar pungkasan saka bangunan sadurunge, Docker ora bakal bisa nemokake lapisan siap kanggo mbangun gambar karo nodejs (tataran builder). Kanggo ngatasi masalah iki, gambar penengah digawe $IMAGE_NAME-builder-stage lan di-push menyang Paket GitHub supaya bisa digunakake ing mbangun sakteruse minangka sumber cache.

Sawetara tips babagan carane nyepetake nggawe gambar Docker. Contone, nganti 30 detik

Total wektu perakitan dikurangi dadi siji lan setengah menit. Setengah menit ngginakaken narik munggah gambar sadurunge.

Preimaging

Cara liya kanggo ngatasi masalah cache Docker sing resik yaiku mindhah sawetara lapisan menyang Dockerfile liyane, mbangun kanthi kapisah, push menyang Registry Container lan digunakake minangka wong tuwa.

Kita nggawe gambar nodejs dhewe kanggo mbangun aplikasi Angular. Nggawe Dockerfile.node ing proyek kasebut

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

Kita ngumpulake lan push gambar umum ing Docker Hub:

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

Saiki ing Dockerfile utama kita nggunakake gambar rampung:

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

Ing conto kita, wektu mbangun ora suda, nanging gambar sing wis dibangun bisa migunani yen sampeyan duwe akeh proyek lan kudu nginstal dependensi sing padha ing saben proyek.

Sawetara tips babagan carane nyepetake nggawe gambar Docker. Contone, nganti 30 detik

Kita ndeleng sawetara cara kanggo nyepetake nggawe gambar docker. Yen sampeyan pengin panyebaran cepet, coba gunakake iki ing proyek sampeyan:

  • nyuda konteks;
  • nggunakake gambar induk cilik;
  • perakitan multistage;
  • ngganti urutan instruksi ing Dockerfile supaya efisien nggunakake cache;
  • nyetel cache ing sistem CI / CD;
  • nggawe awal gambar.

Muga-muga conto kasebut bakal luwih jelas babagan cara kerja Docker, lan sampeyan bakal bisa ngatur panyebaran sampeyan kanthi optimal. Kanggo muter karo conto saka artikel, repositori wis digawe https://github.com/devopsprodigy/test-docker-build.

Source: www.habr.com

Add a comment