Docker
Container building, Compose orchestration, networking, and production optimization
Gives Claude Code expertise in Dockerfile best practices, multi-stage builds, Docker Compose, networking, volume management, image optimization, and security hardening for containerized applications.
Use case: Dockerfile writing, multi-stage build optimization, Docker Compose services, container networking, volume management, image size reduction, security scanning
name: docker
description: Use when writing Dockerfiles, configuring Docker Compose, managing containers, optimizing images, or setting up container networking. Covers multi-stage builds, Compose services, volumes, and security.
# Docker Skill
Quick Start
Essential Commands
docker build -t myapp:v1 . # Build image
docker run -d -p 8080:80 --name web myapp:v1 # Run container
docker compose up -d # Start all services
docker compose down # Stop and remove
docker logs web --tail=100 -f # Follow logs
docker exec -it web /bin/sh # Shell into container
docker ps # List running containers
docker images # List local imagesMulti-Stage Dockerfile (Node.js)
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production=false
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:20-alpine
WORKDIR /app
RUN addgroup -g 1001 appgroup && adduser -u 1001 -G appgroup -s /bin/sh -D appuser
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
USER appuser
EXPOSE 3000
CMD ["node", "dist/index.js"]API Reference
Dockerfile Instructions
| Instruction | Purpose | Example |
|---|---|---|
FROM | Base image | FROM node:20-alpine |
WORKDIR | Set working directory | WORKDIR /app |
COPY | Copy files from host | COPY package*.json ./ |
RUN | Execute command in build | RUN npm ci |
CMD | Default command (overridable) | CMD ["node", "app.js"] |
ENTRYPOINT | Fixed command (args appended) | ENTRYPOINT ["python"] |
ENV | Set environment variable | ENV NODE_ENV=production |
EXPOSE | Document port (informational) | EXPOSE 3000 |
VOLUME | Create mount point | VOLUME ["/data"] |
USER | Set runtime user | USER appuser |
ARG | Build-time variable | ARG VERSION=latest |
HEALTHCHECK | Container health check | HEALTHCHECK CMD curl -f http://localhost/ |
Docker Compose
# docker-compose.yml
services:
web:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/app
depends_on:
db:
condition: service_healthy
volumes:
- ./src:/app/src # Dev: mount source for hot reload
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: app
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
timeout: 5s
retries: 5
volumes:
pgdata:Common Patterns
Layer Caching Optimization
# BAD: Invalidates cache on any file change
COPY . .
RUN npm ci && npm run build
# GOOD: Cache dependencies separately
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run buildNetworking
# Create custom network
docker network create app-network
# Run containers on same network (can reach each other by name)
docker run -d --name db --network app-network postgres:16
docker run -d --name web --network app-network -p 8080:3000 myapp
# Inside web container: db resolves to the postgres containerCompose creates a default network automatically. Services reach each other by service name.
Volume Types
# Named volume (managed by Docker, persistent)
docker volume create mydata
docker run -v mydata:/app/data myapp
# Bind mount (host directory, for development)
docker run -v $(pwd)/src:/app/src myapp
# tmpfs (memory only, no persistence)
docker run --tmpfs /tmp myappImage Optimization
# Use Alpine base (5MB vs 100MB+)
FROM node:20-alpine
# Combine RUN commands (fewer layers)
RUN apk add --no-cache curl && \
npm ci --production && \
npm cache clean --force
# .dockerignore (exclude from COPY)
# node_modules, .git, .env, *.md, tests/Error Handling
| Issue | Cause | Fix |
|---|---|---|
| "port already allocated" | Port in use on host | Change host port or stop conflicting container |
| "no space left on device" | Docker disk full | docker system prune -a (removes unused images/containers) |
| "OOMKilled" | Container exceeded memory limit | Increase mem_limit in Compose or fix memory leak |
| Build cache not working | COPY before dependency install | Restructure Dockerfile for layer caching |
| "network not found" | Container referencing removed network | Recreate network or use Compose (auto-creates) |
Best Practices
- Non-root user: Always add
USER appuserin production Dockerfiles. Never run containers as root. - Multi-stage builds: Separate build dependencies from runtime. Final image should only contain what's needed to run.
- .dockerignore: Always include one. Exclude
node_modules,.git,.env, tests, docs. Speeds up builds and reduces image size. - Pin versions: Use specific image tags (
node:20.11-alpine) notlatest. Pin package versions inRUNcommands. - Health checks: Add
HEALTHCHECKin Dockerfile orhealthcheckin Compose. Enables restart policies and orchestrator health monitoring. - Log rotation: Set in daemon.json:
{"log-driver":"json-file","log-opts":{"max-size":"100m","max-file":"3"}}. Without this, logs grow unbounded. - Secrets: Never
COPY .envinto images. Use Docker secrets, environment variables at runtime, or mount secret files as volumes.