Back to Home
Docker
Building small and secure Docker images with multi-stage builds (Golang example)
multi-stagebuildgolangoptimizationalpinescratch
Docker Multi-Stage Build
Minimize image size with multi-stage builds.
Why Multi-Stage?
- Final image contains only the executable
- Build dependencies are not included in the final image
- Fewer packages = smaller attack surface
- Image size decreases dramatically
Golang Multi-Stage Example
# Stage 1: Build
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/main .
# Stage 2: Run
FROM alpine:3.19
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]
Build and Run
docker build -t my-go-app:latest .
docker run -d -p 8080:8080 my-go-app:latest
docker images my-go-app
Image Size Comparison
| Method | Approximate Size |
|---|---|
| golang:1.22 (single stage) | ~800MB |
| golang:1.22-alpine (single stage) | ~300MB |
| Multi-stage (alpine) | ~15MB |
| Multi-stage (scratch) | ~8MB |
Minimal Image with Scratch
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o main .
FROM scratch
COPY --from=builder /app/main /main
EXPOSE 8080
ENTRYPOINT ["/main"]
Python Multi-Stage Example
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "main.py"]