Dockerfile best practices
Skill VersoXBT/claude-initial-setup/skills/docker/dockerfile-best-practices
Guide for writing production-ready Dockerfiles with multi-stage builds, layer caching, security hardening, and optimized image sizes. Use when the user creates a Dockerfile, asks about Docker image optimization, mentions container security, or needs help with build performance. Trigger whenever Docker or container packaging is discussed.From its SKILL.md
npx -y skills add VersoXBT/claude-initial-setup --skill dockerfile-best-practicesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
4.7 KB, ~1.2k tokens by cl100k_base, as published. Nobody here has run it
Dockerfile Best Practices
Write secure, efficient, and maintainable Dockerfiles that produce minimal production images with proper caching, non-root users, and health checks.
When to Use
- User creates or modifies a Dockerfile
- User asks about reducing Docker image size
- User mentions container security or hardening
- User has slow Docker builds or cache invalidation issues
- User asks about COPY vs ADD or layer ordering
Core Patterns
Multi-Stage Builds
Separate build dependencies from runtime to minimize final image size.
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts
COPY src/ src/
COPY tsconfig.json ./
RUN npm run build
# Stage 2: Production
FROM node:20-alpine AS production
WORKDIR /app
RUN addgroup -g 1001 appgroup && \
adduser -u 1001 -G appgroup -s /bin/sh -D appuser
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/index.js"]
Layer Caching Optimization
Order instructions from least to most frequently changed. Copy dependency manifests before source code so dependency installs are cached across builds.
FROM python:3.12-slim
WORKDIR /app
# System deps change rarely -- cache this layer
RUN apt-get update && \
apt-get install -y --no-install-recommends libpq-dev && \
rm -rf /var/lib/apt/lists/*
# Dependencies change occasionally -- cache this layer
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
# Source code changes frequently -- last layer
COPY . .
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]
Non-Root User
Never run containers as root in production. Create a dedicated user with minimal permissions.
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 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
USER 65534:65534
ENTRYPOINT ["/server"]
.dockerignore
Always include a .dockerignore to prevent sending unnecessary files to the build context.
.git
.github
node_modules
dist
*.md
.env*
.vscode
.idea
docker-compose*.yml
Dockerfile*
coverage
__pycache__
*.pyc
.pytest_cache
Health Checks
Define health checks in the Dockerfile so orchestrators can monitor container health.
# HTTP health check
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:8080/healthz || exit 1
# TCP health check (when curl is unavailable)
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD nc -z localhost 8080 || exit 1
Anti-Patterns
- Using
latesttag: Always pin base image versions (node:20.11-alpine, notnode:latest). Unpinned tags cause non-reproducible builds. - Running as root: Never omit the
USERinstruction. Root in a container is root on the host if the container escapes. - Using ADD instead of COPY: ADD auto-extracts archives and fetches URLs, which is unexpected. Use COPY for local files; use
curlorwgetexplicitly for remote files. - Installing dev dependencies in production: Use
npm ci --omit=devorpip install --no-devin the final stage. - Single-stage builds: Shipping compilers, build tools, and source code in production images wastes space and expands the attack surface.
- Not cleaning up apt/apk cache: Always add
rm -rf /var/lib/apt/lists/*afterapt-get installor use--no-cachewithapk add.
Quick Reference
| Practice | Do | Don't |
|---|---|---|
| Base image | node:20-alpine | node:latest |
| Copy files | COPY . . | ADD . . |
| User | USER 1001 | (run as root) |
| Install deps | RUN npm ci | RUN npm install |
| Layer order | deps before source | source before deps |
| Secrets | --mount=type=secret | COPY .env . |
| Health | HEALTHCHECK CMD ... | (no health check) |
| Cache | rm -rf /var/lib/apt/lists/* | (leave cache) |
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 0 of the 12 instructions most performance cost skills give in ~1.2k tokens
Counted across 797 of the 1,117 authors here whose files we hold, read 2026-09-06
- Check for product marketing context firstin 46 of 797, across 20 files
- Measure before optimizingin 31 of 797, across 25 files
- Profile first to identify the actual bottleneckin 23 of 797, across 22 files
- Verify your robots.txt allows AI crawlersin 21 of 797, across 12 files
- Import directly and avoid barrel filesin 19 of 797, across 15 files
- Spawn all runs in the same turnin 18 of 797, across 11 files
- Write a draft of the skillin 17 of 797, across 10 files
- Understand the user's intentin 17 of 797, across 10 files
- Use React.cache for per-request deduplicationin 16 of 797, across 11 files
- Profile before optimizingin 16 of 797, across 14 files
- Include specific numbers with sourcesin 15 of 797, across 8 files
- Add lazy loading to below-fold imagesin 15 of 797, across 10 files
Said here and by no other author read
- Order instructions from least to most frequently changed
- Create a dedicated non-root user
- Include a .dockerignore file
- Define health checks in the Dockerfile
- Pin base image versions
- Use COPY instead of ADD
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.