Docker — Optimization and Best Practices¶
Optimizing Docker images reduces build time, storage, and runtime overhead while improving security.
Multi-stage Builds¶
Multi-stage builds allow you to use multiple FROM statements in a single Dockerfile, keeping only the final layers in the production image.
# Build stage
FROM golang:1.20-alpine AS build
WORKDIR /app
COPY . .
RUN go build -o /out/myapp
# Runtime stage
FROM alpine:3.19
COPY --from=build /out/myapp /usr/local/bin/myapp
USER 1000
ENTRYPOINT ["/usr/local/bin/myapp"]
Benefits: - Reduces final image size (100MB+ → 10-20MB in this example) - Separates build tools from runtime dependencies - Improves security by excluding compilers and dev packages
General Recommendations¶
Image Size and Layers¶
- Use minimal base images: Alpine, Debian Slim, or distroless where applicable
- Minimize
COPY/ADD: Only copy necessary files; use.dockerignore - Clean in the same layer:
RUN apt-get update && apt-get install -y curl && apt-get clean && rm -rf /var/lib/apt/lists/* - Combine RUN commands: Each
RUNcreates a layer; fewer layers = smaller images
Security¶
- Never run as root: Create an unprivileged user
RUN useradd -m appuser USER appuser - Scan for vulnerabilities:
docker scan myimage trivy image myimage - Keep images updated: Regularly rebuild with latest base images
Secrets and Configuration¶
- Never include secrets in the image or Dockerfile
- Use environment files for configuration:
docker run --env-file .env myimage - Use secret management tools: HashiCorp Vault, Docker Secrets (Swarm), Kubernetes Secrets
Data Persistence¶
- Use volumes for persistent data:
docker run -v my-volume:/data myimage - Never store critical data in container layers; they're ephemeral
Performance Tips¶
| Optimization | Impact | Complexity |
|---|---|---|
| Multi-stage builds | High | Low |
| Layer caching | High | Medium |
| Image size reduction | Medium | Low |
| Security scanning | Medium | Low |
Practical Example: Production-Ready Dockerfile¶
# Build stage
FROM golang:1.21-alpine AS builder
WORKDIR /build
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o app
# Runtime stage
FROM alpine:3.19
RUN apk add --no-cache ca-certificates
RUN adduser -D -u 1000 appuser
WORKDIR /app
COPY --from=builder /build/app .
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1
CMD ["./app"]