Einige Tipps, wie man den Bau von Docker-Images beschleunigen kann. Zum Beispiel bis zu 30 Sekunden.

Bevor eine Funktion in die Produktion gelangt, muss sie in unserer Zeit der komplexen Orchestratoren und CI/CD einen langen Weg vom Commit über die Tests bis zur Auslieferung zurücklegen. Früher konnte man neue Dateien per FTP hochladen (das macht heutzutage niemand mehr, oder?), und der „Deployment“-Prozess dauerte Sekunden. Jetzt müssen wir einen Merge-Request erstellen und eine beträchtliche Zeit warten, bis die Funktion die Nutzer erreicht.

Ein Teil dieses Weges besteht darin, das Docker-Image zu erstellen. Manchmal dauert der Build Minuten, manchmal sogar Dutzende Minuten, was man schwer als normal bezeichnen kann. In diesem Artikel betrachten wir eine einfache Anwendung, die wir in ein Image verpacken, wenden einige Methoden zur Beschleunigung des Builds an und schauen uns die Feinheiten der Funktionsweise dieser Methoden an.

Einige Tipps, wie man den Bau von Docker-Images beschleunigen kann. Zum Beispiel bis zu 30 Sekunden.

Wir haben gute Erfahrungen in der Erstellung und Wartung von Nachrichtenwebseiten: TASS, The Bell, "Neue Zeitung", Republic… Vor nicht allzu langer Zeit haben wir unser Portfolio erweitert, indem wir die Website Remindergelauncht haben. Und während wir schnell neue Funktionen entwickelten und alte Bugs beheben, wurde das langsame Deployment zu einem großen Problem.

Wir führen das Deployment auf GitLab durch. Wir erstellen Images, pushen sie ins GitLab Registry und rollen sie in der Produktion aus. In dieser Liste ist der zeitaufwendigste Teil die Erstellung der Images. Zum Beispiel: Ohne Optimierung dauerte jeder Build des Backends 14 Minuten.

Einige Tipps, wie man den Bau von Docker-Images beschleunigen kann. Zum Beispiel bis zu 30 Sekunden.

Schließlich wurde klar, dass wir so nicht weitermachen konnten, und wir setzten uns hin, um herauszufinden, warum die Images so lange zum Bauen benötigen. Letztendlich gelang es uns, die Bauzeit auf 30 Sekunden zu reduzieren!

Einige Tipps, wie man den Bau von Docker-Images beschleunigen kann. Zum Beispiel bis zu 30 Sekunden.

Für diesen Artikel, um nicht an die Umgebung von Reminder gebunden zu sein, betrachten wir ein Beispiel für den Build einer leeren Anwendung auf Angular. Lassen Sie uns also unsere Anwendung erstellen:

ng n app

Fügen wir PWA hinzu (wir sind schließlich fortschrittlich):

ng add @angular/pwa --project app

Während Millionen von npm-Paketen heruntergeladen werden, lassen Sie uns verstehen, wie ein Docker-Image funktioniert. Docker ermöglicht es, Anwendungen zu verpacken und sie in einer isolierten Umgebung auszuführen, die Container genannt wird. Dank der Isolierung können viele Container gleichzeitig auf einem Server ausgeführt werden. Container sind deutlich leichter als virtuelle Maschinen, da sie direkt auf dem Betriebssystemkern ausgeführt werden. Um einen Container mit unserer Anwendung zu starten, müssen wir zunächst ein Image erstellen, in dem wir alles verpacken, was zur Ausführung unserer Anwendung erforderlich ist. Im Grunde ist ein Image ein Abbild des Dateisystems. Nehmen wir zum Beispiel folgende Dockerfile:

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

Dockerfile ist eine Reihe von Anweisungen; durch das Ausführen jeder dieser Anweisungen wird Docker Änderungen im Dateisystem speichern und sie auf die vorherigen anwenden. Jeder Befehl erzeugt seine eigene Schicht. Das fertige Image ist also eine Kombination dieser Schichten.

Wichtige Informationen: Jede Schicht kann von Docker gecacht werden. Wenn sich seit dem letzten Build nichts geändert hat, wird Docker anstelle der Ausführung des Befehls die bereits vorhandene Schicht verwenden. Da der Hauptzuwachs in der Build-Geschwindigkeit durch die Nutzung des Caches erreicht wird, werden wir bei den Geschwindigkeitsmessungen insbesondere auf den Build des Images mit dem vorhandenen Cache achten. Also folgendermassen:

  1. Löschen Sie die Images lokal, damit vorherige Läufe den Test nicht beeinflussen.
    docker rmi $(docker images -q)
  2. Führen Sie den Build zum ersten Mal aus.
    time docker build -t app .
  3. Ändern Sie die Datei src/index.html – simulate the work of a programmer.
  4. Führen Sie den Build ein zweites Mal aus.
    time docker build -t app .

Wenn die Umgebung für den Build von Images richtig konfiguriert ist (darüber weiter unten mehr), wird Docker beim Start des Builds bereits eine Menge Caches an Bord haben. Unsere Aufgabe ist es, den Cache so zu nutzen, dass der Build möglichst schnell abläuft. Da wir davon ausgehen, dass der Start des Builds ohne Cache nur einmal – beim allerersten Mal – erfolgt, können wir ignorieren, wie langsam dieser erste Versuch war. In den Tests ist der zweite Build wichtig, wenn die Caches bereits vorbereitet sind und wir bereit sind, unseren Kuchen zu backen. Dennoch werden einige Tipps auch den ersten Build beeinflussen.

Legen wir das oben beschriebene Dockerfile in den Projektordner und starten den Build. Alle angeführten Listings wurden zur besseren Lesbarkeit verkürzt.

$ time docker build -t app .
Sending build context to Docker daemon 409MB
Step 1/5 : FROM node:12.16.2
Status: Neuere Image für node:12.16.2 heruntergeladen
Step 2/5 : WORKDIR /app
Step 3/5 : COPY . .
Step 4/5 : RUN npm ci
1357 Pakete in 22.47s hinzugefügt
Step 5/5 : RUN npm run build --prod
Datum: 2020-04-16T19:20:09.664Z - Hash: fffa0fddaa3425c55dd3 - Zeit: 37581ms
Erfolgreich gebaut c8c279335f46
Erfolgreich getaggt app:latest

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

Ändern Sie den Inhalt von src/index.html und führen Sie es ein zweites Mal aus.

$ 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
 ---> Aus dem Cache verwenden
Step 3/5 : COPY . .
Step 4/5 : RUN npm ci
1357 Pakete in 22.47s hinzugefügt
Step 5/5 : RUN npm run build --prod
Datum: 2020-04-16T19:26:26.587Z - Hash: fffa0fddaa3425c55dd3 - Zeit: 37902ms
Erfolgreich gebaut 79f335df92d3
Erfolgreich getaggt app:latest

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

Um zu sehen, ob wir ein Image erhalten haben, führen wir den Befehl aus docker images:

REPOSITORY   TAG      IMAGE ID       CREATED              SIZE
app          latest   79f335df92d3   Vor etwa einer Minute   1.74GB

Vor dem Bau nimmt Docker alle Dateien im aktuellen Kontext und sendet sie an seinen Daemon Build-Kontext an den Docker-Daemon senden 409MB. Der Build-Kontext wird als letztes Argument des Befehls build angegeben. In unserem Fall ist das das aktuelle Verzeichnis – „.“ – und Docker zieht alles, was wir in diesem Ordner haben. 409 MB sind viel: Lassen Sie uns überlegen, wie wir das beheben können.

Wir reduzieren den Kontext

Um den Kontext zu verringern, gibt es zwei Möglichkeiten. Entweder wir legen alle Dateien, die für den Build erforderlich sind, in einen separaten Ordner und geben Docker genau auf diesen Ordner an. Das ist nicht immer bequem, daher gibt es die Möglichkeit, Ausnahmen anzugeben: was nicht in den Kontext gezogen werden soll. Dafür legen wir eine .dockerignore-Datei in das Projekt und geben an, was nicht für den Build benötigt wird:

.git
/node_modules

und führen den Build erneut aus:

$ 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 – deutlich besser als 409 MB. Außerdem haben wir die Bildgröße von 1.74 auf 1.38 GB reduziert:

REPOSITORY   TAG      IMAGE ID       CREATED         SIZE
app          latest   4942f010792a   vor 3 Minuten   1.38GB

Lassen Sie uns versuchen, die Bildgröße weiter zu reduzieren.

Wir verwenden Alpine

Eine weitere Möglichkeit, Größe zu sparen, besteht darin, ein kleines Basisbild zu verwenden. Das Basisbild ist das Bild, auf dessen Grundlage unser Bild erstellt wird. Die untere Schicht wird im Dockerfile angegeben. In unserem Fall verwenden wir ein Bild auf Basis von Ubuntu, auf dem bereits nodejs installiert ist. Und es wiegt … FROM $ docker images -a | grep node node 12.16.2 406aa3abbc6c vor 17 Minuten 916MB

… fast ein Gigabyte. Das Volumen kann erheblich verringert werden, indem ein Bild auf Basis von Alpine Linux verwendet wird. Alpine ist ein sehr kleines Linux. Das Docker-Image für nodejs auf Basis von Alpine wiegt nur 88.5 MB. Lassen Sie uns also unser schwerfälliges Bild ersetzen:

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

Wir mussten einige Dinge installieren, die für den Build der Anwendung erforderlich sind. Ja, Angular lässt sich nicht ohne Python bauen ¯(°_o)\/¯

Aber dafür hat sich die Bildgröße um 150 MB reduziert:

REPOSITORY TAG IMAGE ID CREATED SIZE app latest aa031edc315a vor 22 Minuten 761MB

Wir gehen noch weiter.

Multistage-Build

Nicht alles, was im Bild ist, wird in der Produktion benötigt.

docker run app ls -lah

$ 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

Mit Hilfe von docker run app ls -lah Wir haben einen Container auf Grundlage unseres Images gestartet App und darin einen Befehl ausgeführt ls -lah, wonach der Container seine Arbeit beendet hat.

Im Prod benötigen wir nur den Ordner dist. Die Dateien müssen irgendwie nach außen bereitgestellt werden. Man kann einen HTTP-Server mit Node.js starten. Aber wir machen es einfacher. Ratet ein russisches Wort mit vier Buchstaben „ы“. Richtig! Ынжыныксы. Wir nehmen ein Image mit Nginx, legen darin den Ordner dist und eine kleine Konfiguration ab:

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

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

Das alles können wir mit einem Multi-Stage-Build umsetzen. Ändern wir unser 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 .

Jetzt haben wir zwei Anweisungen FROM im Dockerfile, jede davon startet ihre eigene Build-Phase. Die erste haben wir genannt builder, und ab dem letzten FROM wird unser endgültiges Image erstellt. Im letzten Schritt kopieren wir das Artefakt unseres Builds aus der vorherigen Phase in das endgültige Image mit Nginx. Die Größe des Images hat sich erheblich verringert:

REPOSITORY   TAG      IMAGE ID       CREATED          SIZE
app          latest   2c6c5da07802   vor 29 Minuten   36MB

Lass uns den Container mit unserem Image starten und sicherstellen, dass alles funktioniert:

docker run -p8080:80 app

Mit der Option -p8080:80 haben wir den Port 8080 auf unserer Host-Maschine auf Port 80 im Container weitergeleitet, wo Nginx läuft. Öffnen wir im Browser http://localhost:8080/ und sehen unsere Anwendung. Es funktioniert alles!

Einige Tipps, wie man den Bau von Docker-Images beschleunigen kann. Zum Beispiel bis zu 30 Sekunden.

Die Reduzierung der Image-Größe von 1,74 GB auf 36 MB verkürzt erheblich die Bereitstellungszeit Ihrer Anwendung im Prod. Aber lassen Sie uns zu der Build-Zeit zurückkehren.

$ 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

Wir ändern die Reihenfolge der Schichten

Die ersten drei Schritte wurden bei uns zwischengespeichert (Hinweis Using cache). Im vierten Schritt werden alle Projektdateien kopiert und im fünften Schritt werden die Abhängigkeiten installiert RUN npm ci — ganze 47,338s. Warum sollten wir jedes Mal die Abhängigkeiten neu installieren, wenn sie sich sehr selten ändern? Lassen Sie uns herausfinden, warum sie nicht im Cache gespeichert wurden. Das liegt daran, dass Docker die Schichten schichtweise überprüft, um festzustellen, ob sich der Befehl oder die damit verbundenen Dateien geändert haben. Im vierten Schritt kopieren wir alle Dateien unseres Projekts, und unter ihnen gibt es natürlich Änderungen, weshalb Docker nicht nur diese Schicht nicht aus dem Cache nimmt, sondern auch alle nachfolgenden! Lassen Sie uns einige kleine Änderungen an der Docker-Datei vornehmen.

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 .

Zunächst werden package.json und package-lock.json kopiert, dann die Abhängigkeiten installiert und erst danach wird das gesamte Projekt kopiert. Das Ergebnis:

$ 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 Sekunden statt 3 Minuten — das ist deutlich besser! Die richtige Reihenfolge der Schichten ist wichtig: Zuerst kopieren wir das, was sich nicht ändert, dann das, was sich selten ändert, und zuletzt das, was häufig geändert wird.

Nun ein paar Worte über die Erstellung von Images in CI/CD-Systemen.

Verwendung vorheriger Images zum Caching

Wenn wir eine SaaS-Lösung für den Build verwenden, kann der lokale Docker-Cache sauber und frisch sein. Damit Docker aus dem Cache gebaute Schichten entnehmen kann, geben Sie ihm das vorherige erstellte Image.

Betrachten wir als Beispiel den Build unserer Anwendung in GitHub Actions. Wir verwenden folgende Konfiguration

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

Das Abbild wird in GitHub Packages in zwei Minuten und 20 Sekunden erstellt und gepusht:

Einige Tipps, wie man den Bau von Docker-Images beschleunigen kann. Zum Beispiel bis zu 30 Sekunden.

Jetzt ändern wir den Build so, dass der Cache auf der Grundlage der vorherigen erstellten Abbilder verwendet wird:

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

Zunächst muss erklärt werden, warum zwei Befehle ausgeführt werden. buildDer Grund ist, dass in einer Multi-Stage-Build der resultierende Image ein Satz von Schichten aus der letzten Stage sein wird. Dabei gelangen die Schichten aus vorherigen Stufen nicht in das Abbild. Daher kann Docker beim Verwenden des finalen Abbilds aus dem vorherigen Build keine fertigen Schichten für den Build des Node.js-Images (Stage Builder) finden. Um dieses Problem zu lösen, wird ein Zwischenabild erstellt, $IMAGE_NAME-builder-stage und in GitHub Packages hochgeladen, sodass es in einem nachfolgenden Build als Cache-Quelle verwendet werden kann.

Einige Tipps, wie man den Bau von Docker-Images beschleunigen kann. Zum Beispiel bis zu 30 Sekunden.

Die Gesamtbauzeit wurde auf anderthalb Minuten verkürzt. Eine halbe Minute wird für das Abrufen der vorherigen Abbilder benötigt.

Vorab generierte Abbilder

Ein weiterer Weg, das Problem des sauberen Docker-Caches zu lösen, besteht darin, Teile der Schichten in eine andere Docker-Datei auszulagern, sie separat zu erstellen, im Container-Registry zu pushen und als Elternteil zu verwenden.

Wir erstellen unser eigenes Node.js-Image zum Bauen einer Angular-Anwendung. Im Projekt erstellen wir Dockerfile.node

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

Wir erstellen und pushen ein öffentliches Image in Docker Hub:

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

Jetzt verwenden wir im Haupt-Dockerfile das fertige Image:

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

In unserem Beispiel hat sich die Build-Zeit nicht verringert, aber vordefinierte Images können nützlich sein, wenn Sie viele Projekte haben und in jedem von ihnen die gleichen Abhängigkeiten installieren müssen.

Einige Tipps, wie man den Bau von Docker-Images beschleunigen kann. Zum Beispiel bis zu 30 Sekunden.

Wir haben mehrere Methoden zur Beschleunigung des Docker-Image-Baus betrachtet. Wenn Sie möchten, dass das Deployment schnell erfolgt, versuchen Sie in Ihrem Projekt anzuwenden:

  • Reduzierung des Kontexts;
  • Verwendung kleinerer Basis-Images;
  • Multi-Stage-Bau;
  • Änderung der Anweisungsreihenfolge in Dockerfile, um den Cache effizient zu nutzen;
  • Cache-Einstellungen in CI/CD-Systemen;
  • Vorab-Erstellung von Images.

Ich hoffe, dass anhand des Beispiels klarer wird, wie Docker funktioniert, und dass Sie Ihr Deployment optimal konfigurieren können. Um mit den Beispielen aus dem Artikel zu experimentieren, wurde ein Repository erstellt. https://github.com/devopsprodigy/test-docker-build.

Quelle: habr.com

60GB SSD 8Gb DDR4