Claude Agent Skill · by Josiahsiegel

Docker Best Practices

Install Docker Best Practices skill for Claude Code from josiahsiegel/claude-plugin-marketplace.

Install
Terminal · npx
$npx skills add https://github.com/nextlevelbuilder/ui-ux-pro-max-skill --skill ui-ux-pro-max
Works with Paperclip

How Docker Best Practices fits into a Paperclip company.

Docker Best Practices drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md656 lines
Expand
---name: docker-best-practicesdescription: Comprehensive Docker best practices for images, containers, and production deployments. PROACTIVELY activate for: (1) writing production-ready Dockerfiles, (2) multi-stage builds for lean images, (3) base image selection (distroless, alpine, scratch, slim), (4) layer caching and ordering, (5) .dockerignore hygiene, (6) HEALTHCHECK and graceful shutdown, (7) non-root user and least-privilege patterns, (8) ENV vs ARG and secret handling, (9) tag/digest pinning and reproducibility, (10) Compose for local development. Provides: Dockerfile templates by language, image-size optimization checklist, .dockerignore template, HEALTHCHECK patterns, and Compose dev-stack examples.--- ## 🚨 CRITICAL GUIDELINES ### Windows File Path Requirements **MANDATORY: Always Use Backslashes on Windows for File Paths** When using Edit or Write tools on Windows, you MUST use backslashes (`\`) in file paths, NOT forward slashes (`/`). **Examples:**- ❌ WRONG: `D:/repos/project/file.tsx`- ✅ CORRECT: `D:\repos\project\file.tsx` This applies to:- Edit tool file_path parameter- Write tool file_path parameter- All file operations on Windows systems  ### Documentation Guidelines **NEVER create new documentation files unless explicitly requested by the user.** - **Priority**: Update existing README.md files rather than creating new documentation- **Repository cleanliness**: Keep repository root clean - only README.md unless user requests otherwise- **Style**: Documentation should be concise, direct, and professional - avoid AI-generated tone- **User preference**: Only create additional .md files when user specifically asks for documentation  --- # Docker Best Practices This skill provides current Docker best practices across all aspects of container development, deployment, and operation. ## Image Best Practices ### Base Image Selection **2025 Recommended Hierarchy:**1. **Wolfi/Chainguard** (`cgr.dev/chainguard/*`) - Zero-CVE goal, SBOM included2. **Alpine** (`alpine:3.19`) - ~7MB, minimal attack surface3. **Distroless** (`gcr.io/distroless/*`) - ~2MB, no shell4. **Slim variants** (`node:20-slim`) - ~70MB, balanced **Key rules:**- Always specify exact version tags: `node:20.11.0-alpine3.19`- Never use `latest` (unpredictable, breaks reproducibility)- Use official images from trusted registries- Match base image to actual needs ### Dockerfile Structure **Optimal layer ordering** (least to most frequently changing):```dockerfile1. Base image and system dependencies2. Application dependencies (package.json, requirements.txt, etc.)3. Application code4. Configuration and metadata``` **Rationale:** Docker caches layers. If code changes but dependencies don't, cached dependency layers are reused, speeding up builds. **Example:**```dockerfileFROM python:3.12-slim # 1. System packages (rarely change)RUN apt-get update && apt-get install -y --no-install-recommends \    gcc \    && rm -rf /var/lib/apt/lists/* # 2. Dependencies (change occasionally)COPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txt # 3. Application code (changes frequently)COPY . /appWORKDIR /app CMD ["python", "app.py"]``` ### Multi-Stage Builds Use multi-stage builds to separate build dependencies from runtime: ```dockerfile# Build stageFROM node:20-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ciCOPY . .RUN npm run build # Production stageFROM node:20-alpine AS runtimeWORKDIR /app# Only copy what's needed for runtimeCOPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesUSER nodeCMD ["node", "dist/server.js"]``` **Benefits:**- Smaller final images (no build tools)- Better security (fewer attack vectors)- Faster deployment (smaller upload/download) ### Layer Optimization **Combine commands** to reduce layers and image size: ```dockerfile# Bad - 3 layers, cleanup doesn't reduce sizeRUN apt-get updateRUN apt-get install -y curlRUN rm -rf /var/lib/apt/lists/* # Good - 1 layer, cleanup effectiveRUN apt-get update && \    apt-get install -y --no-install-recommends curl && \    rm -rf /var/lib/apt/lists/*``` ### .dockerignore Always create `.dockerignore` to exclude unnecessary files: ```# Version control.git.gitignore # Dependenciesnode_modules__pycache__*.pyc # IDE.vscode.idea # OS.DS_StoreThumbs.db # Logs*.loglogs/ # Testingcoverage/.nyc_output*.test.js # DocumentationREADME.mddocs/ # Environment.env.env.local*.local``` ## Container Runtime Best Practices ### Security ```bashdocker run \  # Run as non-root  --user 1000:1000 \  # Drop all capabilities, add only needed ones  --cap-drop=ALL \  --cap-add=NET_BIND_SERVICE \  # Read-only filesystem  --read-only \  # Temporary writable filesystems  --tmpfs /tmp:noexec,nosuid \  # No new privileges  --security-opt="no-new-privileges:true" \  # Resource limits  --memory="512m" \  --cpus="1.0" \  my-image``` ### Resource Management Always set resource limits in production: ```yaml# docker-compose.ymlservices:  app:    deploy:      resources:        limits:          cpus: '2.0'          memory: 1G        reservations:          cpus: '1.0'          memory: 512M``` ### Health Checks Implement health checks for all long-running containers: ```dockerfileHEALTHCHECK --interval=30s --timeout=3s --retries=3 --start-period=40s \  CMD curl -f http://localhost:3000/health || exit 1``` Or in compose:```yamlservices:  app:    healthcheck:      test: ["CMD", "curl", "-f", "http://localhost/health"]      interval: 30s      timeout: 3s      retries: 3      start_period: 40s``` ### Logging Configure proper logging to prevent disk fill-up: ```yamlservices:  app:    logging:      driver: "json-file"      options:        max-size: "10m"        max-file: "3"``` Or system-wide in `/etc/docker/daemon.json`:```json{  "log-driver": "json-file",  "log-opts": {    "max-size": "10m",    "max-file": "3"  }}``` ### Restart Policies ```yamlservices:  app:    # For development    restart: "no"     # For production    restart: unless-stopped     # Or with fine-grained control (Swarm mode)    deploy:      restart_policy:        condition: on-failure        delay: 5s        max_attempts: 3        window: 120s``` ## Docker Compose Best Practices ### File Structure ```yaml# No version field needed (Compose v2.40.3+) services:  # Service definitions  web:    # ...  api:    # ...  database:    # ... networks:  # Custom networks (preferred)  frontend:  backend:    internal: true volumes:  # Named volumes (preferred for persistence)  db-data:  app-data: configs:  # Configuration files (Swarm mode)  app-config:    file: ./config/app.conf secrets:  # Secrets (Swarm mode)  db-password:    file: ./secrets/db_pass.txt``` ### Network Isolation ```yamlnetworks:  frontend:    driver: bridge  backend:    driver: bridge    internal: true  # No external access services:  web:    networks:      - frontend   api:    networks:      - frontend      - backend   database:    networks:      - backend  # Not accessible from frontend``` ### Environment Variables ```yamlservices:  app:    # Load from file (preferred for non-secrets)    env_file:      - .env     # Inline for service-specific vars    environment:      - NODE_ENV=production      - LOG_LEVEL=info     # For Swarm mode secrets    secrets:      - db_password``` **Important:**- Add `.env` to `.gitignore`- Provide `.env.example` as template- Never commit secrets to version control ### Dependency Management ```yamlservices:  api:    depends_on:      database:        condition: service_healthy  # Wait for health check      redis:        condition: service_started   # Just wait for start``` ## Production Best Practices ### Image Tagging Strategy ```bash# Use semantic versioningmy-app:1.2.3my-app:1.2my-app:1my-app:latest # Include git commit for traceabilitymy-app:1.2.3-abc123f # Environment tagsmy-app:1.2.3-productionmy-app:1.2.3-staging``` ### Secrets Management **Never do this:**```dockerfile# BAD - secret in layer historyENV API_KEY=secret123RUN echo "password" > /app/config``` **Do this:**```bash# Use Docker secrets (Swarm) or external secret managementdocker secret create db_password ./password.txt # Or mount secrets at runtimedocker run -v /secure/secrets:/run/secrets:ro my-app # Or use environment files (not in image)docker run --env-file /secure/.env my-app``` ### Monitoring & Observability ```yamlservices:  app:    # Health checks    healthcheck:      test: ["CMD", "curl", "-f", "http://localhost/health"]      interval: 30s     # Labels for monitoring tools    labels:      - "prometheus.io/scrape=true"      - "prometheus.io/port=9090"      - "com.company.team=backend"      - "com.company.version=1.2.3"     # Logging    logging:      driver: "json-file"      options:        max-size: "10m"        max-file: "3"``` ### Backup Strategy ```bash# Backup named volumedocker run --rm \  -v VOLUME_NAME:/data \  -v $(pwd):/backup \  alpine tar czf /backup/backup-$(date +%Y%m%d).tar.gz -C /data . # Restore volumedocker run --rm \  -v VOLUME_NAME:/data \  -v $(pwd):/backup \  alpine tar xzf /backup/backup.tar.gz -C /data``` ### Update Strategy ```yamlservices:  app:    # For Swarm mode - rolling updates    deploy:      replicas: 3      update_config:        parallelism: 1        # Update 1 at a time        delay: 10s            # Wait 10s between updates        failure_action: rollback        monitor: 60s      rollback_config:        parallelism: 1        delay: 5s``` ## Platform-Specific Best Practices ### Linux - Use user namespace remapping for added security- Leverage native performance advantages- Use Alpine for smallest images- Configure SELinux/AppArmor profiles- Use systemd for Docker daemon management ```json// /etc/docker/daemon.json{  "userns-remap": "default",  "log-driver": "json-file",  "log-opts": {    "max-size": "10m",    "max-file": "3"  },  "storage-driver": "overlay2",  "live-restore": true}``` ### macOS - Allocate sufficient resources in Docker Desktop- Use `:delegated` or `:cached` for bind mounts- Consider multi-platform builds for ARM (M1/M2)- Limit file sharing to necessary directories ```yaml# Better volume performance on macOSvolumes:  - ./src:/app/src:delegated  # Host writes are delayed  - ./build:/app/build:cached  # Container writes are cached``` ### Windows - Choose container type: Windows or Linux- Use forward slashes in paths- Ensure drives are shared in Docker Desktop- Be aware of line ending differences (CRLF vs LF)- Consider WSL2 backend for better performance ```yaml# Windows-compatible pathsvolumes:  - C:/Users/name/app:/app  # Forward slashes work  # or  - C:\Users\name\app:/app  # Backslashes need escaping in YAML``` ## Performance Best Practices ### Build Performance ```bash# Use BuildKit (faster, better caching)export DOCKER_BUILDKIT=1 # Use cache mountsRUN --mount=type=cache,target=/root/.cache/pip \    pip install -r requirements.txt # Use bind mounts for dependenciesRUN --mount=type=bind,source=package.json,target=package.json \    --mount=type=bind,source=package-lock.json,target=package-lock.json \    --mount=type=cache,target=/root/.npm \    npm ci``` ### Image Size - Use multi-stage builds- Choose minimal base images- Clean up in the same layer- Use .dockerignore- Remove build dependencies ```dockerfile# Install and cleanup in one layerRUN apt-get update && \    apt-get install -y --no-install-recommends \    package1 \    package2 && \    apt-get clean && \    rm -rf /var/lib/apt/lists/*``` ### Runtime Performance ```dockerfile# Use exec form (no shell overhead)CMD ["node", "server.js"]  # Good# vsCMD node server.js         # Bad - spawns shell # Optimize signalsSTOPSIGNAL SIGTERM # Run as non-root (slightly faster, much more secure)USER appuser``` ## Security Best Practices Summary **Image Security:**- Use official, minimal base images- Scan for vulnerabilities (Docker Scout, Trivy)- Don't include secrets in layers- Run as non-root user- Keep images updated **Runtime Security:**- Drop capabilities- Use read-only filesystem- Set resource limits- Enable security options- Isolate networks- Use secrets management **Compliance:**- Follow CIS Docker Benchmark- Implement container scanning in CI/CD- Use signed images (Docker Content Trust)- Maintain audit logs- Regular security reviews ## Common Anti-Patterns to Avoid ❌ **Don't:**- Run as root- Use `--privileged`- Mount Docker socket- Use `latest` tag- Hardcode secrets- Skip health checks- Ignore resource limits- Use huge base images- Skip vulnerability scanning- Expose unnecessary ports- Use inefficient layer caching- Commit secrets to Git ✅ **Do:**- Run as non-root- Use minimal capabilities- Isolate containers- Tag with versions- Use secrets management- Implement health checks- Set resource limits- Use minimal images- Scan regularly- Apply least privilege- Optimize build cache- Use .env.example templates ## Checklist for Production-Ready Images - [ ] Based on official, versioned, minimal image- [ ] Multi-stage build (if applicable)- [ ] Runs as non-root user- [ ] No secrets in layers- [ ] .dockerignore configured- [ ] Vulnerability scan passed- [ ] Health check implemented- [ ] Proper labeling (version, description, etc.)- [ ] Efficient layer caching- [ ] Resource limits defined- [ ] Logging configured- [ ] Signals handled correctly- [ ] Security options set- [ ] Documentation complete- [ ] Tested on target platform(s) This skill represents current Docker best practices. Always verify against official documentation for the latest recommendations, as Docker evolves continuously.