3秒でわかる
Dockerfile を複数の段に分け、ビルド用の段で作った成果物だけを実行用の段へ移す書き方。イメージを小さく安全にするための定番です。
もう少し詳しく
どういうものか
マルチステージビルドは、1つの Dockerfile に FROM を複数書き、それぞれを独立した段として扱う仕組みです。前の段でコンパイルやバンドルを行い、COPY --from で必要なファイルだけを次の段へ持ち込みます。
最終的にイメージとして残るのは最後の段だけです。途中の段で入れたコンパイラやテスト用のパッケージは、成果物に一切含まれません。
なぜ必要か
ビルドに必要な道具と、動かすのに必要な道具は別物です。同じ段で全部やると、コンパイラもソースも中間ファイルもそのまま出荷されます。イメージが数百 MB 膨らみ、起動やデプロイが遅くなるだけでなく、攻撃者が侵入したときに使える道具まで一緒に渡すことになります。
段を分ければ、最終イメージには実行に要るものだけが残ります。Go のように静的リンクできる言語では、最終段をほぼ空にできます。
具体例
# --- build stage ---
FROM golang:1.23 AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/app ./cmd/server
# --- runtime stage ---
FROM gcr.io/distroless/static-debian12
COPY /out/app /app
USER nonroot
ENTRYPOINT ["/app"]go.mod を先にコピーしているのは、依存が変わらない限り go mod download の層を再利用させるためです。
つまずきやすいところ
COPY --from のパスを間違え、空のディレクトリを持ってきてしまう。ビルド段で ls を挟んで出力先を確かめます--mount=type=secret を使いますARG を段をまたいで使おうとする。値は段ごとに宣言し直す必要があります似た用語との違い
| 語 | 指すもの |
|---|---|
| レイヤ | 1命令ごとにできる差分。同じ段の中の話 |
| ステージ | FROM で始まる独立した工程 |
| ベースイメージ | 各段の出発点になるイメージ |
覚え方
工場と店。工場で作って、店には完成品だけを並べます。工具を店頭に置かないのがマルチステージの目的です。