Was ist ein mehrstufiger Build in Docker?

A multi-stage build in Docker allows developers to use multiple FROM statements in a single Dockerfile. This technique optimizes image size by separating the build environment from the final product.
Inhaltsverzeichnis
Ein Multi-Stage-Build in Docker ist ein leistungsstarkes Feature, das es ermöglicht, Docker-Images effizienter und sicherer zu erstellen. Es erlaubt die Verwendung mehrerer FROM-Anweisungen in einer einzigen Dockerfile-Datei, wobei jede FROM-Anweisung einen neuen Build-Stage einleitet und ein Basis-Image auswählt. Dies ermöglicht es, Artefakte aus einem Stage in einen anderen zu kopieren, wodurch die endgültige Docker-Image-Größe reduziert werden kann.In einem Multi-Stage-Build können Sie beispielsweise einen Stage für die Kompilierung oder das Erstellen von Abhängigkeiten und einen anderen Stage für die Ausführung der Anwendung verwenden. Der erste Stage kann alle notwendigen Tools und Abhängigkeiten enthalten, während der zweite Stage nur die kompilierten Binärdateien oder die fertige Anwendung enthält. Dies führt zu einem kleineren und sichereren finalen Image, da keine unnötigen Build-Tools oder Quellcode enthalten sind.Hier ist ein einfaches Beispiel für ein Dockerfile mit Multi-Stage-Build:```dockerfile# Stage 1: Build stageFROM golang:1.16 AS builderWORKDIR /appCOPY . .RUN go build -o main .# Stage 2: Production stageFROM alpine:latestRUN apk --no-cache add ca-certificatesWORKDIR /root/COPY --from=builder /app/main .CMD ["./main"]```In diesem Beispiel wird die Anwendung in der ersten Stage mit dem `golang:1.16` Image kompiliert. In der zweiten Stage wird ein minimales `alpine:latest` Image verwendet, und nur die kompilierte Binärdatei wird in das finale Image kopiert. Dies reduziert die Größe des finalen Images erheblich.Multi-Stage-Builds sind besonders nützlich für Sprachen wie Java, C++ oder Go, bei denen die Kompilierung ressourcenintensiv sein kann und das finale Image nur die kompilierten Artefakte enthalten sollte. Sie tragen auch zur Verbesserung der Sicherheit bei, da potenziell gefährliche Build-Tools nicht im finalen Image enthalten sind.

Verständnis von Multi-Stage-Builds in DockerIn diesem Artikel werden wir Multi-Stage-Builds in Docker untersuchen. Wir werden sehen, wie sie funktionieren und wie sie uns helfen können, unsere Docker-Images zu optimieren.Was sind Multi-Stage-Builds?Multi-Stage-Builds sind eine Funktion in Docker, die es uns ermöglicht, mehrere FROM-Anweisungen in einer Dockerfile zu verwenden. Jede FROM-Anweisung kann eine Basis-Image verwenden, und jede von ihnen beginnt einen neuen Build-Stadium. Wir können selektiv Dateien von einem Stadium zum anderen kopieren, wodurch wir alles auswählen können, was wir in das endgültige Image übernehmen möchten.Warum Multi-Stage-Builds verwenden?Multi-Stage-Builds sind nützlich, wenn wir ein optimiertes Image erstellen möchten. Zum Beispiel, wenn wir eine Anwendung kompilieren müssen, die bestimmte Abhängigkeiten erfordert, aber diese Abhängigkeiten nicht im endgültigen Image benötigen. Mit Multi-Stage-Builds können wir diese Abhängigkeiten im ersten Stadium installieren, die Anwendung kompilieren und dann nur die kompilierte Anwendung in das endgültige Image kopieren.Ein Beispiel für einen Multi-Stage-BuildLassen Sie uns ein einfaches Beispiel für einen Multi-Stage-Build betrachten. Angenommen, wir haben eine Go-Anwendung, die wir in ein Docker-Image packen möchten. Wir können ein Multi-Stage-Build verwenden, um die Anwendung zu kompilieren und dann nur die kompilierte Binärdatei in das endgültige Image zu kopieren.```dockerfile # Erstes Stadium: Kompilieren der Anwendung FROM golang:1.16 AS builder WORKDIR /app COPY . . RUN go build -o main .# Zweites Stadium: Erstellen des endgültigen Images FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /app/main . CMD ["./main"] ```In diesem Beispiel verwenden wir das erste Stadium, um die Go-Anwendung zu kompilieren. Wir verwenden das `golang:1.16` Image als Basis und kopieren den Quellcode in das Arbeitsverzeichnis. Dann kompilieren wir die Anwendung mit dem `go build` Befehl.Im zweiten Stadium erstellen wir das endgültige Image. Wir verwenden das `alpine:latest` Image als Basis und installieren die `ca-certificates` Pakete. Dann kopieren wir die kompilierte Binärdatei aus dem ersten Stadium in das Arbeitsverzeichnis des endgültigen Images. Schließlich setzen wir den Befehl, der ausgeführt werden soll, wenn der Container gestartet wird.FazitMulti-Stage-Builds sind eine leistungsstarke Funktion in Docker, die es uns ermöglicht, optimierte Images zu erstellen. Sie sind besonders nützlich, wenn wir Anwendungen kompilieren müssen, die bestimmte Abhängigkeiten erfordern, aber diese Abhängigkeiten nicht im endgültigen Image benötigen. Mit Multi-Stage-Builds können wir diese Abhängigkeiten im ersten Stadium installieren, die Anwendung kompilieren und dann nur die kompilierte Anwendung in das endgültige Image kopieren.

Docker has revolutionized the way we think about building, shipping, and running applications. As the demand for lightweight, efficient, and easily deployable applications continues to rise, so does the need for advanced techniques that streamline the development workflow. One such technique is the multi-stage build, which plays an essential role in optimizing Docker images. This article will explain what multi-stage builds are, their benefits, how they work, and best practices for using them effectively.

Was ist ein Multi-Stage Build?

Ein Multi-Stage-Build ist eine Funktion in Docker, die die Verwendung mehrerer ermöglicht. FROM Anweisungen in einer einzigen Dockerdatei. Es ermöglicht die Erstellung optimierter Images, indem die Build-Umgebung von der Laufzeitumgebung getrennt wird. Bei einem mehrstufigen Build können Sie Ihre Anwendung in einer Stufe kompilieren und dann nur die notwendigen Artefakte in einer anderen Stufe in das finale Image kopieren. Dies verringert die Größe des finalen Images und enthält nur die Dateien, die zum Ausführen der Anwendung benötigt werden, was dazu beiträgt, Ihre Container leichtgewichtig und effizient zu halten.

Diese leistungsstarke Funktion wurde in Docker 17.05 eingeführt und ist seitdem eine beliebte Praxis unter Entwicklern, die ihre Docker-Workflows optimieren möchten.

Why Use Multi-Stage Builds?

1. Reduzierte Bildgröße

Einer der bedeutendsten Vorteile von Multi-Stage-Builds ist die Reduzierung der Image-Größe. Traditionelle Docker-Builds enthalten oft unnötige Build-Abhängigkeiten und Dateien im endgültigen Image, was zu aufgeblähten Images führen kann. Mit Multi-Stage-Builds können Sie sicherstellen, dass nur die für die Laufzeit benötigten Dateien im endgültigen Image enthalten sind. Dies spart nicht nur Festplattenspeicher, sondern beschleunigt auch den Bereitstellungsprozess, indem die Zeit zum Herunterladen des Images aus einer Registry reduziert wird.

2. Simplified Dockerfile

Mehrstufige Builds können Ihre Dockerfile vereinfachen, indem man sie in separate Stufen aufteilt. Jede Stufe kann ihren eigenen Satz an Abhängigkeiten und Konfigurationen haben, was eine bessere Organisation und Klarheit ermöglicht. Entwickler können leicht erkennen, was gebaut wird, wie es gebaut wird und was in der finalen Image enthalten ist.

3. Verbesserte Sicherheit

Indem die Anzahl der Dateien und Abhängigkeiten im finalen Image minimiert wird, können mehrstufige Builds die Sicherheit erhöhen. Eine geringere Angriffsfläche bedeutet weniger potenzielle Schwachstellen. Zudem können Sie vermeiden, Entwicklerwerkzeuge, Build-Skripte und andere sensible Informationen im Produktionsimage zu enthalten.

4. Optimierte Build-Zeiten

Mehrstufige Builds können die Build-Zeiten verbessern, indem sie das Zwischenspeichern von Zwischenebenen ermöglichen. Docker cached jede Ebene eines Images, sodass Docker eine unveränderte Ebene in späteren Builds wiederverwenden kann. Durch die effektive Aufteilung Ihres Dockerfiles in Stages können Sie diesen Caching-Mechanismus nutzen und die für Builds aufgewendete Zeit reduzieren.

5. Flexibilität in Build-Umgebungen

Mehrstufige Builds ermöglichen es, für jede Stufe unterschiedliche Basis-Images zu verwenden. Beispielsweise könnte man ein umfangreicheres Image mit allen Entwicklungsabhängigkeiten zum Bauen der Anwendung nutzen und ein minimales Image für die finale Laufzeitumgebung. Diese Flexibilität ermöglicht es, die Images basierend auf den spezifischen Anforderungen jeder Stufe zu optimieren.

How Multi-Stage Builds Work

To understand how multi-stage builds work, let’s break down the process with an example. Consider a simple application written in Go. In a traditional Dockerfile, you might see something like this:

FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .

FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]

Explanation of the Example

  1. Erste Stufe (Bauphase)

    In the first stage, we use the official Go image (golang:1.16) als Basis-Image. Dieses Image enthält alle notwendigen Werkzeuge zur Kompilierung von Go-Anwendungen. Wir setzen das Arbeitsverzeichnis auf /app, kopieren Sie den Anwendungscode in den Container und führen Sie ihn aus go build command to compile the application. The result is a binary executable named myapp.

  2. Second Stage (Final Stage)

    In the second stage, we use a much smaller base image, alpine:latest, which is minimal and designed for running applications. We set the working directory to /app Bitte geben Sie den vollständigen Text an, den Sie übersetzt haben möchten. COPY --from=builder Befehl zum Kopieren der kompilierten Binärdatei aus der ersten Stufe in dieses endgültige Image.

  3. Running the Application

    Schließlich geben wir den Befehl an, um unsere Anwendung mit dem auszuführen. CMD directive. The resulting image is significantly smaller since it only contains the myapp binary and the minimal runtime environment.

Multi-Stage Build with Multiple Stages

Sie können auch komplexere mehrstufige Builds erstellen, die mehrere Stufen umfassen. Beispielsweise möchten Sie vielleicht in einer bestimmten Stufe Tests durchführen, bevor Sie zum finalen Image übergehen. Hier ist ein Beispiel für eine mehrstufige Dockerfile, die eine Testphase enthält:

FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .

FROM golang:1.16 AS test
WORKDIR /app
COPY --from=builder /app/myapp .
RUN go test ./...

FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]

In this case, we added a testing stage that uses the Go image again. The tests will be run against the binary built in the first stage. If the tests pass, the final stage will copy the binary into the Alpine image.

Best Practices for Multi-Stage BuildsMulti-stage builds are a powerful feature in Docker that allow you to create optimized and efficient container images by separating the build process into multiple stages. This approach helps reduce the final image size, improve security, and enhance overall performance. Here are some best practices to follow when working with multi-stage builds:1. Use a .dockerignore file: - Create a .dockerignore file in your project directory to exclude unnecessary files and directories from being copied into the build context. - This helps reduce the build time and the size of the final image by excluding files that are not needed for the application to run.2. Leverage build arguments: - Use build arguments (ARG) to pass variables during the build process. - This allows you to customize the build based on different environments or configurations without modifying the Dockerfile.3. Optimize layer caching: - Arrange your Dockerfile instructions in a way that maximizes layer caching. - Place instructions that are less likely to change (e.g., installing dependencies) at the top of the file. - This ensures that these layers are cached and reused in subsequent builds, reducing build time.4. Use specific base images: - Choose base images that are tailored to your application's needs. - Avoid using generic or bloated base images that include unnecessary packages or tools. - This helps reduce the final image size and improves security by minimizing the attack surface.5. Clean up after each stage: - Remove unnecessary files, dependencies, or build artifacts after each stage. - This helps keep the intermediate images clean and reduces the final image size.6. Use multi-stage builds for different environments: - Create separate stages for different environments (e.g., development, testing, production). - This allows you to include additional tools or configurations specific to each environment without affecting the final production image.7. Minimize the number of stages: - While multi-stage builds offer flexibility, try to minimize the number of stages whenever possible. - Each additional stage adds complexity and increases the build time.8. Use COPY --from to copy artifacts: - Utilize the COPY --from instruction to copy artifacts from one stage to another. - This allows you to selectively copy only the necessary files from the build stage to the final stage.9. Consider using a non-root user: - Create a non-root user in the final stage and switch to that user. - This enhances security by reducing the privileges of the running container.10. Test and validate the final image: - After building the final image, thoroughly test and validate it to ensure it meets your requirements. - Check the image size, verify the application's functionality, and perform security scans if necessary.By following these best practices, you can create efficient and optimized multi-stage builds that result in smaller, more secure, and performant container images.

Um aus mehrstufigen Builds das Beste herauszuholen, beachten Sie folgende Best Practices:

1. Verwenden Sie spezifische Tags für Basis-Images

When specifying base images, use specific tags instead of latest. Die Verwendung spezifischer Tags hilft sicherzustellen, dass Ihre Builds reproduzierbar sind und nicht aufgrund unerwarteter Änderungen im Basis-Image brechen.

2. Keep Stages Focused

Jede Stufe sollte eine einzige Verantwortung haben. Zum Beispiel sollte eine Stufe dem Erstellen der Anwendung gewidmet sein, während eine andere das Testen oder Verpacken übernimmt. Dies macht Ihre Dockerfile einfacher zu warten und zu verstehen.

3. Für Caching optimieren

Nutzen Sie den Caching-Mechanismus von Docker, indem Sie Ihre Befehle strategisch anordnen. Platzieren Sie Befehle, die sich selten ändern, ganz oben, damit Docker diese Ebenen zwischenspeichern und nachfolgende Builds beschleunigen kann.

4. Minimieren Sie Ebenen

While multi-stage builds can help reduce image size, be mindful of the number of layers you create. Each command in a Dockerfile creates a new layer, so consider combining commands where appropriate to minimize the number of layers.

5. Clean Up Build Artifacts

If you have any temporary files or build artifacts that are not needed in the final image, make sure to clean them up in the final stage. This further reduces the size of the image and enhances security.

6. Nutzen Sie Umgebungsvariablen

You can use environment variables to configure your application at runtime. By defining variables in the final stage, you can keep your build stages clean and focused on their specific tasks.

Fazit

Multi-stage builds are a powerful feature in Docker that enables developers to create optimized, efficient, and secure images. By leveraging this technique, you can significantly reduce image sizes, improve build times, and keep your Dockerfiles organized and manageable. As containerization continues to gain traction, understanding and implementing multi-stage builds will be an essential skill for developers looking to streamline their workflows and enhance their applications.

Indem Sie bewährte Verfahren befolgen und Multi-Stage-Builds effektiv nutzen, können Sie sicherstellen, dass Ihre Docker-Images nicht nur leichtgewichtig, sondern auch sicher und leistungsfähig sind, wodurch Ihre Anwendungen für die Bereitstellung in der heutigen schnelllebigen Entwicklungsumgebung bereit sind.