Docker多阶段构建:FROM指令引用前阶段的行为及与仓库镜像的区分
Great question! Let’s break this down clearly since the FROM-as-stage pattern is super useful but often overlooked compared to COPY --from.
1. What happens when you use FROM to reference a previous build stage?
When you use FROM <stage-name-or-index> where <stage-name-or-index> refers to an earlier stage defined with AS name (like FROM builder), Docker directly uses the intermediate image created by that earlier stage as the base for your new stage.
This intermediate image includes everything from the prior stage: all installed dependencies, copied files, environment variables, and filesystem layers—exactly the state the stage was in after running all its instructions. It’s essentially reusing the local build artifact without pushing it to a registry first, which saves time and disk space.
Here’s a concrete example to show the behavior:
# Stage 1: Build a Go application FROM golang:1.21 AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o myapp ./cmd/server # Stage 2: Reuse the builder stage directly as the base FROM builder # No need to COPY the binary—it’s already present in /app/myapp! CMD ["/app/myapp"]
In the second stage, FROM builder pulls in the full state of the builder stage. This means your final image will include the Go runtime and all build artifacts, which is useful if you need the build tools in your final image (unlike the more common pattern of copying just the binary to a slim image).
You can also reference stages by their numeric index (starting from 0 for the first stage). For example, FROM 0 would do the same as FROM builder in the example above.
2. How to distinguish between a build stage and a remote registry image in FROM?
Docker follows a simple priority rule to resolve what FROM is referencing:
- Local build stage first: If the name you specify (e.g.,
builder) matches a stage defined earlier in the same Dockerfile withAS name, Docker will use that local stage. The same goes for numeric indexes (like0,1)—these always refer to local stages, since registry images don’t use pure numeric names. - Registry image only if no stage matches: If the name doesn’t match any existing stage, Docker will treat it as a registry image and attempt to pull it (from Docker Hub by default, or a specified registry if you include the full path like
my-registry.com/my-image:tag).
Examples to clarify:
- If you have
AS builderdefined and runFROM builder: Docker uses the local builder stage. - If you don’t have a builder stage and run
FROM builder: Docker will search Docker Hub for an image namedbuilder(and fail if it doesn’t exist). - If you have a stage named
alpinebut want to use the official Alpine registry image instead, explicitly specify the registry path:FROM docker.io/alpine:latest. This tells Docker to ignore the local stage and pull the remote image.
内容的提问来源于stack exchange,提问作者Patrick J. S.

