fivenines
12/40
Lesson 12 · Images

Multi-Stage Builds

In one sentence: A multi-stage build runs several build pipelines in one file and lets a later stage copy just the artifacts out of an earlier one — so compilers and build tools never ship in the final image.

You already know

  • From Lesson 10: every RUN and COPY becomes a permanent layer in the image.
  • From Lesson 8: smaller images = fewer blobs to store, verify, and transfer.

The fat-image problem

Compiling inside a build means your image contains a compiler — forever. A 10 MB binary rides atop 900 MB of toolchain layers that serve no runtime purpose and widen the attack surface. Deleting the tools in a later instruction doesn't help: the earlier layers still exist underneath (Lesson 9 — lowers are immutable). The layered model itself makes subtraction impossible; the fix has to be structural.

Build here, ship from there

A multi-stage file defines multiple FROM stages, each its own pipeline with its own layers. The magic instruction is COPY --from=builder: it reaches into a previous stage's filesystem and copies files into the current stage. The final image contains only the last stage's layers; earlier stages are scaffolding, discarded after the build. Stages without dependencies can even build in parallel.

Architecture — two pipelines, one artifact bridge
flowchart LR
  subgraph S1["stage 1: builder (discarded)"]
    F1["FROM toolchain (900 MB)"] --> C1["COPY src/"] --> R1["RUN compile → /out/bin"]
  end
  subgraph S2["stage 2: runtime (shipped)"]
    F2["FROM minimal base (10 MB)"] --> C2["COPY --from=builder /out/bin"] --> M2["CMD /bin"]
  end
  R1 -- "artifact bridge:
only /out/bin crosses" --> C2 S2 --> IMG["final image ≈ 20 MB
(zero toolchain layers)"] style S1 fill:#fff8ec,stroke:#f2ddb0 style IMG fill:#f0faf2,stroke:#1f7a34
Sequence — what the builder actually does
sequenceDiagram
  participant B as Builder
  participant S1 as stage 1 (toolchain)
  participant S2 as stage 2 (minimal)
  B->>S1: build all stage-1 layers (compile)
  S1-->>B: filesystem contains /out/bin
  B->>S2: build stage-2 layers
  B->>S1: read /out/bin
  B->>S2: COPY into stage 2 → one small layer
  B-->>B: tag ONLY stage 2 as the image
  note over S1: stage 1 layers stay in build cache
but never ship

Anchor these

  • Layers can't subtract — deleting files later never shrinks an image.
  • COPY --from is a one-way artifact bridge between stage filesystems.
  • Only the final stage ships; builder stages are cache-only scaffolding.
Next step

See what actually stuck.

Take the practice scenarios now.