Awesome-omni-skill dockerfile-optimization
Optimize Dockerfiles for smaller images, faster builds, better caching, and security. Use this skill when writing, reviewing, or debugging Dockerfiles.
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/devops/dockerfile-optimization" ~/.claude/skills/diegosouzapw-awesome-omni-skill-dockerfile-optimization && rm -rf "$T"
manifest:
skills/devops/dockerfile-optimization/SKILL.mdsource content
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)
- System packages (rarely changes)
- Dependency manifests (changes occasionally)
- Dependency install (changes with manifests)
- Source code (changes frequently)
- Build step (changes with source)
Image Size Optimization
Use Alpine or Distroless Base Images
| Base | Size | Use When |
|---|---|---|
| 0 MB | Static Go binaries |
| ~2 MB | Java, Go, Python without shell |
| ~7 MB | Need a shell, package manager |
| ~80 MB | Need Debian packages |
| ~200+ MB | Development only, never production |
Reduce Layer Count
# BAD — 3 layers RUN apt-get update RUN apt-get install -y curl RUN rm -rf /var/lib/apt/lists/* # GOOD — 1 layer, cleaned up RUN apt-get update && \ apt-get install -y --no-install-recommends curl && \ rm -rf /var/lib/apt/lists/*
Use .dockerignore
Create a
.dockerignore to exclude unnecessary files:
.git node_modules dist *.md .env* .vscode .idea __pycache__ *.pyc coverage .next
Security Best Practices
Run as Non-Root
# Create a non-root user RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser # Or use built-in user USER node # Node.js images USER nobody:nobody # Generic
Pin Versions
# BAD — unpredictable FROM node:latest RUN apt-get install python3 # GOOD — reproducible FROM node:22.12-alpine3.19 RUN apk add --no-cache python3=3.11.6-r0
Don't Store Secrets in Images
# BAD — secret baked into image ENV API_KEY=sk-secret123 COPY .env . # GOOD — pass at runtime # docker run -e API_KEY=sk-secret123 myapp # or use Docker secrets / mount
Scan for Vulnerabilities
# Docker Scout docker scout cves myimage:latest # Trivy trivy image myimage:latest # Grype grype myimage:latest
Common Anti-Patterns
| Anti-Pattern | Problem | Fix |
|---|---|---|
| Large, unpredictable | Use or , pin version |
before | Breaks caching | Copy manifests first, install, then copy source |
alone | Stale package list cached | Combine with in one |
in production | Security risk | Create and switch to non-root user |
No | Bloated context, slow builds | Add with exclusions |
without form | Signals not forwarded | Use form |
| Not cleaning up in same layer | Larger image | Combine install + cleanup in one |
Health Checks
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1
Debugging Dockerfiles
# Build with progress output docker build --progress=plain . # Build up to a specific stage docker build --target builder . # Inspect image layers docker history myimage:latest # Run shell in failed build docker run -it --entrypoint /bin/sh myimage:latest # Check image size breakdown docker image inspect myimage:latest --format='{{.Size}}' dive myimage:latest # Interactive layer explorer