Skip to content

Multi-stage Dockerfile instructions pattern

The Multi-stage Dockerfile instructions pattern is an advanced build technique used to create smaller, more secure, and more efficient container images. Instead of defining the application build and runtime environment in a single stage, this pattern utilizes multiple FROM instructions to separate the build environment from the final runtime environment^[600-developer__docker__Dockerfile__docker-ssh.md].

Core Mechanism

The defining characteristic of this pattern is the use of sequential FROM instructions within a single Dockerfile^[600-developer__docker__Dockerfile__docker-ssh.md]. Each FROM instruction initializes a new build stage, resetting the build environment^[600-developer__docker__Dockerfile__docker-ssh.md].

  • Base Images: You can use completely different base images for each stage (e.g., a heavy compiler image for building and a slim alpine image for the final output).
  • Artifact Transfer: Files needed in the final image are copied from previous stages using the --from=... flag with the COPY instruction^[600-developer__docker__Dockerfile__docker-ssh.md].
  • Discard Context: By default, the filesystem artifacts from previous stages are discarded, leaving only the artifacts you explicitly copy in the final image^[600-developer__docker__Dockerfile__docker-ssh.md].

Benefits

  • Reduced Image Size: Build tools (like compilers, package managers, and source code) are not included in the final runtime image, significantly reducing the footprint^[600-developer__docker__Dockerfile__docker-ssh.md].
  • Improved Security: A smaller attack surface is achieved by removing unnecessary libraries and tools that are present in build environments but not required for runtime^[600-developer__docker__Dockerfile__docker-ssh.md].
  • Separation of Concerns: The complexity of dependency management is isolated to the build stage, while the runtime stage remains simple and focused on execution^[600-developer__docker__Dockerfile__docker-ssh.md].

Example

The following example demonstrates a multi-stage build where a Java application is prepared in the first stage, and only the necessary artifact is run in the final stage^[600-developer__docker__Dockerfile__docker-ssh.md]:

# Build Stage
FROM java:8 AS builder
WORKDIR /app
COPY src .
RUN javac Main.java

# Runtime Stage
FROM java:8
WORKDIR /app
# Copy only the compiled class from the builder stage
COPY --from=builder /app/Main.class .
CMD ["java", "Main"]

Sources

  • 600-developer__docker__Dockerfile__docker-ssh.md