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
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.
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.
$ 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!)
$ 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.
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.
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)
Recommended Posts