Soweit ich weiß, sind Build-Phasen in Docker grundlegende Dinge, und ich habe ein praktisches Verständnis dafür, aber ich habe Probleme, eine richtige Definition zu finden, und ich kann auch keine finden.

Also: Was ist die Definition einer Docker Build-Phase ?

Bearbeiten: Ich frage nicht "Wie verwende ich eine Build-Phase?" oder "Wie kann ich Multi-Build-Stufen verwenden?" welche Leute scheinen sehr gespannt zu sein zu antworten :-)

Der Grund, warum ich diese Frage habe, ist, dass ich die folgenden Sätze in den Dokumenten :

  • "Der FROM-Befehl initialisiert eine neue Build-Phase."
  • "Einer neuen Bauphase kann ein Name gegeben werden"

Was mich wunderte: Was genau ist eine Build-Phase?

3
Niels Bom 17 Apr. 2018 im 13:07

5 Antworten

Beste Antwort

Ich glaube nicht, dass es jemals eine strenge Definition für Docker-Build-Phase geben wird, da eine Build-Phase im Allgemeinen etwas Theoretisches ist, das:

  • kann von Ihnen definiert werden
  • hängt von Ihrem Fall ab (Sprache / Bibliotheken)

In dieser Frage: Unterschied zwischen Build und Deployment? Eine der Antworten lautet ...

Erstellen bedeutet, das Projekt zu kompilieren .

Ich denke, Sie können es auch so sehen. Eine Erstellungsphase ist eine Prozedur, die etwas generiert, das später verwendet werden kann.

Die Idee mit mehrstufigen Docker-Builds ist:

  1. Generieren Sie, was Sie brauchen werden
  2. Lassen Sie das zurück, was Sie nicht benötigen, und verwenden Sie das Produkt aus Schritt 1 leichter

Wenn Sie die Dokumente gelesen haben, hat Alex Ellis ein schönes Beispiel, in dem dieselbe Logik stattfindet:

  1. Er beginnt mit einem golang Image, fügt Bibliotheken hinzu und erstellt seine App (Go generiert eine ausführbare Binärdatei).
  2. Danach braucht er Golang und die Bibliotheken nicht mehr, um es zu versenden / auszuführen. Er wählt ein alpine Image aus, fügt die ausführbare Datei aus Schritt 1 hinzu und versendet seine App mit einem Image, das viel kleiner ist.
1
tgogos 17 Apr. 2018 im 12:19

Seit Version 17 unterstützt docker jetzt mehrere Phasen während einer docker build Ausführung.

Dies bedeutet, dass Sie nicht mehr nur ein Quellbild in Ihrer Docker-Datei definieren und den gesamten Build in einem einzigen Lauf ausführen müssen. Sie können jedoch mehrere Stufen mit unterschiedlichen Bildern in Ihrem Dockerfile für jede Stufe mit mehreren {definieren {X1}} Definitionen:

# Build stage
FROM microsoft/aspnetcore
# ..do a build with a dev image for creating ./app artifact

# Publish - use a hardened, production image
FROM alpine:latest
CMD ["./app"]  

Dies gibt Ihnen den Vorteil, dass Sie Ihren Image-Erstellungsprozess unterbrechen können, um ihn für eine Aufgabe zu optimieren, die Sie in einer Phase ausführen. Die folgenden Phasen können beispielsweise sein:

  1. Verwenden Sie ein Bild mit zusätzlichen Flusenabhängigkeiten, um Ihre Quelle zu überprüfen
  2. Verwenden Sie ein Dev-Image mit allen bereits installierten Entwicklungsabhängigkeiten, um Ihre Quelle zu erstellen
  3. Verwenden Sie ein anderes Bild einschließlich Test-Frameworks, um verschiedene Tests für die Artefakte durchzuführen
  4. Wenn alles in Ordnung ist, verwenden Sie ein minimales, optimiertes und gehärtetes Bild, um die endgültigen Artefakte für die Produktion zu erfassen

Lesen Sie mehr über multistage-build:

2
muratiakos 17 Apr. 2018 im 10:35

Eine Build-Phase beginnt mit einer FROM-Anweisung und endet mit dem Schritt vor der nächsten FROM-Anweisung

1
LeslieK 15 Mai 2020 im 01:48

Eine Bühne ist die Schaffung eines Bildes. In einem mehrstufigen Build erstellen Sie mehr als ein Image, kennzeichnen jedoch normalerweise nur ein einziges (Ausnahmen sind mehrere Builds, das Erstellen eines Multi-Architektur-Image-Manifests mit einem Tool wie buildx und alles andere Docker) Veröffentlichungen nach dieser Antwort).


Jede Phase, in der ein bestimmtes Bild erstellt wird, beginnt mit einer FROM - Zeile in der Docker-Datei. Eine Stufe erbt nichts, was in früheren Stufen getan wurde, sondern basiert auf einem eigenen Basisimage. Wenn Sie also Folgendes haben:

FROM alpine as stage1
RUN apk add your_tool

FROM alpine as stage2
RUN your_tool some args

Sie erhalten eine Fehlermeldung, da your_tool in der zweiten Stufe nicht installiert ist.


Welche Stufe erhalten Sie als Ausgabe vom Build? Standardmäßig die letzte Stufe, aber Sie können dies mit docker image build --target stage1 . ändern, um die Stufe mit dem Namen stage1 in diesem Beispiel zu erstellen. Der klassische Docker-Build wird vom oberen Rand der Docker-Datei ausgeführt, bis die Zielphase abgeschlossen ist. Buildkit erstellt ein Abhängigkeitsdiagramm und erstellt Phasen gleichzeitig und nur bei Bedarf. Verlassen Sie sich also nicht auf diese Reihenfolge, um einen Testworkflow in Ihrer Docker-Datei zu steuern (Buildkit kann feststellen, ob in Ihrer Release-Phase nichts in der Testphase erforderlich ist, und das Erstellen überspringen der Test).


Was ist der Wert mehrerer Stufen? In der Regel wird die Build-Umgebung von der Laufzeitumgebung getrennt. Sie können den gesamten Build innerhalb von Docker ausführen. Dies hat zwei Vorteile.

Erstens benötigen Sie kein externes Makefile und verschiedene auf dem Host installierte Compiler und andere Tools, um die Binärdateien zu kompilieren, die dann mit einer COPY - Zeile in das Image kopiert werden. Jeder mit Docker kann Ihr Image erstellen.

Und zweitens enthält das resultierende Image nicht alle Compiler oder andere Tools zur Erstellungszeit, die zur Laufzeit nicht benötigt werden, was zu kleineren und sichereren Images führt. Das typische Beispiel ist eine Java-App mit Maven und einem vollständigen JDK zum Erstellen, eine Laufzeit mit nur der JAR-Datei und der JRE.


Wenn jede Phase ein separates Image erstellt, wie können Sie die JAR-Datei von der Erstellungsphase zur Ausführungsphase bringen? Dies ergibt sich aus einer neuen Option für den Befehl COPY, --from. Ein stark vereinfachter mehrstufiger Build sieht aus wie:

FROM maven as build
COPY src /app/src
WORKDIR /app/src
RUN mvn install

FROM openjdk:jre as release
COPY --from=build /app/src/target/app.jar /app
CMD java -jar /app/app.jar

Mit diesem COPY --from=build können wir das in der Build-Phase erstellte Artefakt in die Release-Phase aufnehmen, ohne etwas anderes aus dieser ersten Phase einzubeziehen (es werden keine Schichten von Kompilierungswerkzeugen wie JDK oder Maven zu unserer zweiten hinzugefügt Bühne).


Wie arbeiten FROM x as y und COPY --from=y /a /b zusammen? Das FROM x as y definiert einen Bildnamen für die Dauer dieses Builds, in diesem Fall y. Überall später in der Docker-Datei, wo Sie einen Bildnamen eingeben würden, können Sie y eingeben, und Sie erhalten das Ergebnis dieser Phase als Eingabe. Man könnte also sagen:

FROM upstream as mybuilder
RUN apk add common_tools

FROM mybuilder as stage2
RUN some_tool arg2

FROM mybuilder as stage3
RUN some_tool arg3

FROM minimal_base as release
COPY --from=stage2 /bin2 /
COPY --from=stage3 /bin3 /

Beachten Sie, wie stage2 und stage3 jeweils FROM mybuilder sind, die die Ausgabe der ersten Stufe sind.

Mit COPY --from=y können Sie den Kontext, aus dem Sie kopieren, in ein anderes Image anstelle des Build-Kontexts ändern. Es muss keine andere Etappe sein. So können Sie beispielsweise Folgendes tun, um eine Docker-Binärdatei in Ihrem Bild zu erhalten:

FROM alpine
COPY --from=docker:stable /usr/local/bin/docker /usr/local/bin/

Weitere Dokumentation hierzu finden Sie unter: https://docs.docker.com / Develop / Develop-Images / Multistage-Build /

1
BMitch 15 Mai 2020 im 02:36

Bühne | steɪdʒ |
Nomen
Ein Punkt, eine Periode oder ein Schritt in einem Prozess oder einer Entwicklung

Nehmen Sie ein praktisches Beispiel: Sie möchten ein Image erstellen, das einen produktionsbereiten Webserver mit in Javascript kompilierten Typescript-Dateien enthält. Sie möchten dieses Typoskript in einem Docker-Container erstellen, um das Abhängigkeitsmanagement zu vereinfachen. Also brauchst du:

  • node.js
  • Typoskript
  • Alle für die Kompilierung erforderlichen Abhängigkeiten
  • Webpack oder was auch immer
  • Nginx / Apache / was auch immer

In Ihrem endgültigen Bild benötigen Sie nur die kompilierten .js-Dateien und beispielsweise nginx. Aber um dorthin zu gelangen, brauchen Sie zuerst all das andere Zeug. Wenn Sie das endgültige Bild hochladen, enthält es alle Zwischenebenen, auch wenn sie für das endgültige Produkt nicht erforderlich sind.

Mit Docker-Erstellungsphasen können Sie diese Stufen oder Schritte jetzt tatsächlich in separate Bilder unterteilen, während Sie immer noch nur eine Docker-Datei verwenden und nicht mehrere Docker-Dateien mit der externen Shell zusammenkleben müssen Skripte oder so. Z.B.:

FROM node as builder
RUN npm install ...
# whatever you need to build your files

FROM nginx as production
COPY --from=builder /final.js /var/www/html

Das Endergebnis dieser Docker-Datei ist ein kleines Bild mit nginx als Basis plus nur der endgültigen .js-Datei. Es enthält nicht alle unnötigen Dinge wie node.js und die npm-Abhängigkeiten.

builder Hier ist die erste Stufe , production ist die zweite Stufe . In diesem Fall wird die erste Stufe am Ende des Prozesses verworfen. Sie können jedoch auch eine bestimmte Stufe mit docker build --target=builder erstellen. Ein neues FROM führt eine neue, separate Stufe ein. Sie sind im Wesentlichen separate Docker-Dateien, können jedoch Daten mit COPY --from gemeinsam nutzen.

0
deceze 17 Apr. 2018 im 12:40