Mustafa CavusogluMC

Command Palette

Search for a command to run...

AboutExperiencesProjects
Linux3Docker7Git4Kubernetes4Network2uv1Miniconda1
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

MethodApproximate 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"]