[Docker] Ist es gut genug, um es als mehrstufigen Build zu bezeichnen? → Die Geschichte, die so gut wurde

Fazit

Durch die Nutzung mehrstufiger Builds kann die Größe von Container-Images erheblich reduziert werden. Das Folgende ist ein Beispiel für eine Nuxt.js-Anwendung.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
nuxt                single-stage        fba421d5de5b        About a minute ago   371MB
nuxt                multi-stage         a40d0000d0a8        10 minutes ago       22MB

Überprüfungsverfahren

Umgebung

Erstellen Sie eine Nuxt-Anwendung

Erstellen Sie eine Nuxt.js-Anwendung mit npx create-nuxt-app <Anwendungsname>. Die Zusammensetzung ist frei. Unabhängig davon, wie Sie es einstellen, erhalten Sie das gleiche Ergebnis mit einigen Größenunterschieden.

Fügen Sie dem Stammverzeichnis die folgenden Dateien hinzu

Dockerfile-Single

FROM node:lts-alpine
WORKDIR /app
COPY . ./
RUN npm install -g http-server && \
    npm install && \
    npm run build
EXPOSE 8080
CMD [ "http-server", "dist" ]

Der Einfachheit halber werden nicht mehrstufige Builds in diesem Artikel als einstufige Builds bezeichnet. Ich habe den richtigen Begriff nicht verstanden, also lassen Sie es mich bitte wissen, wenn Sie damit vertraut sind! Ich habe den "http-Server" mitgebracht, um die Anwendung auszuführen und die erstellten Dateien darauf abzulegen.

Dockerfile-Multi

FROM node:lts-alpine AS build-stage
WORKDIR /app
COPY . ./
RUN npm install && \
    npm run build

FROM nginx:stable-alpine AS production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD [ "nginx", "-g", "daemon off;" ]

Die Build-Phase verwendet das Image node.js und die Ausführungsphase das Nginx-Image. Sie können die Stufe mit "as" benennen und angeben, von welcher Stufe die Datei mit "--from" stammt. Das in der Erstellungsphase endgültig generierte Verzeichnis wird im Stammverzeichnis des Nginx-Dokuments abgelegt.

.dockerignore

.dockerignore


node_modules
dist
Dockerfile*

Die Docker-Datei ist wie ein Fehler, aber die node_modules und dist schwellen an, je nachdem, was Sie verwenden. Schließen Sie es während der Image-Erstellungsphase aus, da es im Container durch "npm install" bzw. "npm build" ausgeführt wird.

Erstellen Sie jedes Image und überprüfen Sie den Vorgang

Für einstufig

$ docker build -t nuxt:single-stage --file Dockerfile-Single .
$ docker run -dit -p 8080:8080 --name nuxt-single nuxt:single-stage
$ docker exec nuxt-single wget -S -O- localhost:8080
Connecting to localhost:8080 (127.0.0.1:8080)
  HTTP/1.1 200 OK
(Unten weggelassen: OK, wenn HTML als Antwortdaten zurückgegeben wird!)

Für mehrstufige

$ docker build -t nuxt:multi-stage --file Dockerfile-Multi .
$ docker run -dit -p 80:80 --name nuxt-multi nuxt:multi-stage 
$ docker exec nuxt-multi wget -S -O- localhost:80
Connecting to localhost:80 (127.0.0.1:80)
  HTTP/1.1 200 OK
(Unten weggelassen: OK, wenn HTML als Antwortdaten zurückgegeben wird!)

Wenn Sie zu diesem Zeitpunkt jede Bildgröße vergleichen, erhalten Sie das am Anfang angezeigte Ergebnis.

Verwendung eines mehrstufigen Builds

In diesem Beispiel wird die Größe des Bildes reduziert, indem verworfen wird, was beim Erstellen der Anwendung erforderlich ist, nicht jedoch beim Ausführen. Mit anderen Worten kann gesagt werden, dass ein mehrstufiger Build effektiv ist, wenn ein Image eines Containers erstellt wird, für den nur eine Ausführungsumgebung erforderlich ist. Beispielsweise muss ein Container für CI / CD nur ein Liefergegenstand des Builds sein. Durch Dateien, die nur zum Zeitpunkt des Builds erforderlich sind, wird die Containergröße unnötig erhöht. Es ist eine gute Verwendung für mehrstufige Builds.

Beiseite

Sie können die durch "npm install" verursachte Netzwerkkommunikation reduzieren, indem Sie "node_modules" aus ".dockerignore" entfernen und "npm install" weglassen. Es gibt keinen großen Zeitunterschied zwischen dem einmaligen Senden von "node_modules" an den Docker-Daemon und dem Ausführen von "npm install", abhängig von der Netzwerkumgebung.

Bei Verwendung eines mehrstufigen Builds bleibt das Zwischenbild außerdem "<none: none>". Um dies zu vermeiden, führen Sie einen der folgenden Schritte aus:

In Verwandte GitHub-Ausgabe wird es durch "Spezifikation (kostenlose Übersetzung)" abgeschnitten, kann jedoch nicht als Option verwaltet werden oder der Image Builder wird aktualisiert. Es scheint eine Debatte darüber gegeben zu haben, ob damit umgegangen werden könnte. Derzeit scheint es die Hauptzeile zu sein, den neuen Builder (BuildKit) zum Standard zu machen. (Selbst wenn ich BuildKit verwende, frage ich mich, wie groß der Unterschied zwischen Docker-Image-Bereinigung und Docker-Builder-Bereinigung ist ...? ... Nur Zwischenbilder und Caches, die einem bestimmten Build entsprechen Ich möchte löschen)

Referenz

Recommended Posts

[Docker] Ist es gut genug, um es als mehrstufigen Build zu bezeichnen? → Die Geschichte, die so gut wurde
Die Geschichte, ein Projekt zu bauen, das Maven mit Ant gebaut hat
Über die Angelegenheit, die tendenziell mit ARG von Dockerfile verwechselt wird, einem mehrstufigen Build
Ich möchte Apache Wicket 8 zusammenfassen, weil es eine gute Idee ist
Shell-Skript, das ein Docker-Image erstellt und an ECR weiterleitet
[Docker] Erstellen, wenn der Quellcode auf dem Container gebunden ist
[Java small story] Überwachen Sie, wann der Liste ein Wert hinzugefügt wird
Suchen Sie einen geeigneten Wert für eine Methode und machen Sie sie zu einem ValueObject
Das zu RestTemplate hinzugefügte patchForObject kann nicht effektiv verwendet werden, wenn es sich um eine Standardimplementierung handelt (die HttpURLConnection verwendet).
Die Geschichte, dass .java auch in Unity 2018 erstellt wurde
[Swift] Die Geschichte, dass der Schalter oft für die Aufzählung verwendet wird
Eine Geschichte, die unter einem Raum litt, der nicht verschwindet, selbst wenn er mit Java beschnitten ist
Eine Geschichte über das Erstellen eines Builders, der den Builder erbt
Grundlagen der Java-Fehlerbehandlung - Die Geschichte, die abfängt, wird nur im Vordergrund aufgegriffen
PATH geht nicht vorbei ... Die Ursache ist der Zeichencode
Die Geschichte, dass das erzwungene Update nicht implementiert werden konnte
[Docker] Ist es gut genug, um es als mehrstufigen Build zu bezeichnen? → Die Geschichte, die so gut wurde
Eine Geschichte, die Zeit brauchte, um eine Verbindung herzustellen
Eine Geschichte über das Erstellen eines Builders, der den Builder erbt
[Rails] [Docker] Kopieren und Einfügen ist in Ordnung! So erstellen Sie eine Rails-Entwicklungsumgebung mit Docker
Das Ende der katastrophalen Programmierung # 03 "Der Vergleich von ganzen Zahlen, wenn" a> b ", nimmt an, dass es" a - b> 0 "ist."
Eine Geschichte über die Schwierigkeiten beim Versuch, PHP 7.4 auf CentOS 8 von GCE zu erstellen
Erstellen Sie ein Paket, das ein allgemeiner Entwicklungsteil von Automation Anywhere A2019 # 1 ist. ~ Erstellen und verwenden Sie zunächst das SDK-Beispiel so wie es ist