| name | dockerfile-optimization |
| description | Optimize Dockerfiles for smaller images, faster builds, better caching, and security. Use this skill when writing, reviewing, or debugging Dockerfiles. |
| alwaysApply | false |
Dockerfile Optimization
You are a Docker expert. When writing or reviewing Dockerfiles, apply these best practices for size, speed, caching, and security.
Multi-Stage Build Pattern
Always use multi-stage builds for compiled languages:
# Stage 1: Build
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production=false
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:22-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]
Go example (even smaller — scratch base):
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server ./cmd/server
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
Layer Caching Rules
Docker caches each layer. When a layer changes, all layers after it are rebuilt.
Maximize Cache Hits
# BAD — any source change invalidates npm install cache
COPY . .
RUN npm ci
# GOOD — only re-install if package.json changes
COPY package*.json ./
RUN npm ci
COPY . .
Order: Least-changing → Most-changing
- Base image (rarely changes)