# マルチステージ build とは？より小さいイメージ、よりクリーンな出力

> マルチステージ build は複数の FROM stage を使い、build ツールを最終イメージから締め出します。仕組み、例、そしてイメージサイズを激減させる理由を学びましょう。

Source: https://latchkey.dev/ja/learn/ci-explained/what-is-a-multi-stage-build  
Updated: 2026-06-26

マルチステージ build は使い捨ての stage でコンパイルし、完成した artifact だけを小さな最終 stage にコピーします - そのためイメージは toolchain ではなく出力を出荷します。

build ツール、コンパイラ、dev 依存関係は artifact を生成するのに必要ですが、それを実行するのには不要です。マルチステージ Dockerfile では、重い builder stage を使ってから、出荷するものだけを含む新しく最小限の最終 stage を開始できます。その結果、劇的に小さく安全なイメージが得られます。

## 中心となる考え方

1 つの Dockerfile に複数の `FROM` stage を宣言します。前段の stage が重労働を行い、最終 stage はクリーンに始まり `COPY --from=<stage>` でコンパイル済みの出力だけを引き込みます。前段の stage に残されたものはすべて破棄されます。

## Go の例

stage 1:
`FROM golang:1.22 AS build`
`WORKDIR /src`
`COPY . .`
`RUN go build -o app .`
stage 2:
`FROM gcr.io/distroless/static`
`COPY --from=build /src/app /app`
`ENTRYPOINT ["/app"]`
最終イメージにはバイナリだけがあり、他には何もありません。

## なぜイメージがこれほど小さくなるのか

Go の toolchain イメージは数百メガバイトですが、最終的な distroless イメージは数メガバイトです。`COPY --from` の artifact だけが最終 stage に着地するため、その build の重さはすべて決して出荷されません。

## その他の利点

- パッケージが少ないことは、実行中のイメージの脆弱性が少ないことを意味します。
- build 中に使う secret は builder stage に留めておけます。
- 1 つのファイルから複数の最終 stage（例: test と prod）をターゲットにできます。

## CI におけるマルチステージ build

マルチステージ build は各 stage をキャッシュするため、変更のない builder ステップはスキップされます。キャッシュが温まったマネージド runner では、高コストなコンパイル stage が job 間で再利用され、最終コピーだけが再実行されます。

## Applying this to your pipeline

- Measure before changing. Most CI optimisation targets the wrong step because the slow one is assumed rather than timed.
- Cache what is expensive to produce and cheap to validate, and key the cache to the exact tool version.
- Fail fast: run the cheapest checks that can reject a change first, so an expensive job never starts on code that cannot pass.
- Prefer determinism over speed when they conflict. A fast pipeline nobody trusts gets re-run, which is slower than a slow one that is believed.

## FAQ

### What is What is a Multi-Stage Build? smaller Images, cleaner output?

Build tools, compilers, and dev dependencies are needed to produce an artifact but not to run it. A multi-stage Dockerfile lets you use a heavy builder stage and then start a fresh, minimal final stage that contains only what you ship. The result is a dramatically smaller and safer image.

### The core idea?

You declare multiple FROM stages in one Dockerfile. Earlier stages do the heavy lifting; the final stage starts clean and uses COPY --from=<stage> to pull in just the compiled output. Everything left behind in earlier stages is discarded.

### A Go example?

Stage one: FROM golang:1.22 AS build WORKDIR /src COPY . . RUN go build -o app . Stage two: FROM gcr.io/distroless/static COPY --from=build /src/app /app ENTRYPOINT ["/app"] The final image has the binary and nothing else.

### Why it shrinks images so much?

The Go toolchain image is hundreds of megabytes; the final distroless image is a few. Because only the COPY --from artifact lands in the final stage, all of that build weight never ships.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
