Files
open-claw-team/.openclaw/workspace/skills/docker-patterns/SKILL.md
T

3.9 KiB

name, description
name description
docker-patterns Docker and Docker Compose best practices — multi-stage builds, networking, volumes, container security, optimization. Use when writing Dockerfiles, docker-compose.yml, or containerizing applications.

Docker Patterns

Based on ECC docker-patterns skill.

Dockerfile Best Practices

Pin base image versions

# Good
FROM node:20.11.0-alpine3.19

# Bad — version changes can break builds
FROM node:latest

Multi-Stage Builds for minimal images

# Stage 1: Build
FROM golang:1.22-bookworm AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o myapp -ldflags="-s -w"

# Stage 2: Runtime (small image)
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/myapp /myapp
USER 1000
CMD ["/myapp"]

Layer caching optimization

# Copy dependency files first, install, then copy rest
COPY package.json package-lock.json ./
RUN npm ci --production=false
COPY . .

.dockerignore

node_modules/
.git/
.env
dist/
*.log
__pycache__
*.pyc

Docker Compose Patterns

Production-ready compose

name: myapp
services:
  app:
    image: myapp:${APP_VERSION:-latest}
    restart: unless-stopped
    environment:
      DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/myapp
      NODE_ENV: production
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:3000/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks: [app-net]
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: "0.5"

  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  app-net:
    driver: bridge

volumes:
  pgdata:

Container Security

Run as non-root

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

No sensitive data in images

  • Never COPY .env files
  • Never hardcode credentials in Dockerfile
  • Use docker secrets, env vars at runtime

Minimize attack surface

  • Use Alpine or distroless base images
  • Remove build tools from final image (multi-stage)
  • Only expose needed ports

Scan images

# Scan for vulnerabilities
docker scout cve myapp:latest

# Scan Dockerfile for issues
hadolint Dockerfile

Networking

Service-to-service communication

# Compose: services can reach each other by name
# app can reach db at hostname "db" on port 5432

Isolating networks

networks:
  frontend:  # Public-facing services
  backend:   # DB, cache (not exposed to outside)

Volumes

Named volumes (data persistence)

volumes:
  - pgdata:/var/lib/postgresql/data  # Persisted data
  - redis-data:/data

Bind mounts (development)

volumes:
  - ./src:/app/src:ro  # Read-only code mount
  - /data:/app/logs    # Log output

Optimization Tips

  1. Smallest base image: scratch > alpine > slim > full
  2. Layer count: Fewer layers = smaller image
  3. COPY order: Dependencies first, then application code
  4. Combined RUN commands: RUN apt-get update && apt-get install -y x && rm -rf /var/lib/apt/lists/*
  5. Multi-stage: Build tools in builder, runtime only in final
  6. Distroless for Go/Rust: FROM scratch with just the binary

Checklist

  • Base image pinned to specific version
  • Multi-stage build for production
  • Non-root user
  • .dockerignore complete
  • Health checks configured
  • No secrets in image
  • Minimal base image
  • Volumes for persistent data
  • Network isolation