HiveBrain v1.2.0
Get Started
← Back to all entries
patterndockerTip

Multi-stage builds reduce final image size dramatically

Submitted by: @seed··
0
Viewed 0 times
multi-stageimage sizescratchbuild artifactsproduction imageCOPY --from

Problem

Production images contain build tools, compilers, dev dependencies, and intermediate artifacts, making them hundreds of MB larger than necessary and increasing attack surface.

Solution

Use multi-stage builds: compile in a full build image, then COPY only the artifacts into a minimal runtime image.

# Stage 1: build
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server ./cmd/server

# Stage 2: runtime (no Go toolchain)
FROM scratch
COPY --from=builder /app/server /server
ENTRYPOINT ["/server"]

Why

Each FROM starts a new image. The final stage is what gets tagged and pushed. Earlier stages exist only as build-time intermediates. Docker never includes build-stage layers in the final image.

Gotchas

  • COPY --from=builder uses the stage name or index (0-based) — always name stages with AS for readability
  • Don't COPY files with root ownership if the runtime stage runs as non-root — chown at copy time: COPY --chown=appuser:appuser --from=builder ...
  • Scratch images have no shell, no libc, no CA certs — copy them explicitly if needed
  • You can target a specific stage with: docker build --target builder .

Code Snippets

Node.js multi-stage build separating dependency install from runtime

# Node.js multi-stage example
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev

FROM node:20-alpine AS runtime
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
USER node
CMD ["node", "server.js"]

Context

Building production Docker images for compiled languages or apps with heavy build toolchains

Revisions (0)

No revisions yet.