In this lesson, you will learn how to use multiple FROM instructions in a single Dockerfile to decouple your build environment from your final runtime environment.
The Problem with Single-Stage Builds
When you build an application, you often need a variety of heavy tools: compilers, build systems (like Maven or Make), and source code libraries. However, your final container doesn't need the compiler—it only needs the compiled binary or the static web files. If you use one FROM instruction, your final image ends up "bloated" with all the source code and development tools, which increases the security attack surface and makes the image unnecessarily large.
The Multi-Stage Solution
By defining multiple FROM instructions, you instruct Docker to treat the Dockerfile as a series of separate stages. Each FROM starts a fresh, clean slate. You can build your app in the first stage, and then "cherry-pick" only the finished artifacts into the second stage.
Consider this structure:
# Stage 1: The "Build" environment
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o my-app
# Stage 2: The "Production" environment
FROM alpine:latest
WORKDIR /root/
# Copy only the compiled binary from the builder stage
COPY --from=builder /app/my-app .
CMD ["./my-app"]
How it Works
- Isolation: The first stage (
builder) contains the Go compiler and your source code. Once theRUNcommand finishes, you have your binary. - Clean Slate: The second
FROMinstruction starts a brand new image based onalpine:latest. This image is tiny and knows nothing about the Go compiler or the source code files. - Selective Copying: The
COPY --from=buildercommand reaches back into the previous stage and pulls out only the file you actually need to run the application.
Everything else from the builder stage—the source code, the compiler, and the temporary build logs—is discarded. The resulting image is lean, secure, and production-ready.
Key Takeaway: Defining multiple FROM instructions allows you to separate heavy build-time tools from your lightweight production runtime, resulting in significantly smaller and more secure images.