Skip to main content

docker

This skill MUST be loaded when ANY Dockerfile, docker-compose.yml, docker-compose.override.yml, .dockerignore, or Docker-related configuration file is being read, reviewed, edited, or created. Also use when the user asks to "create a Dockerfile", "write a multi-stage build", "add a .dockerignore", "set up docker-compose", "containerize an application", "optimize a Docker image", "reduce Docker image size", "fix Docker build issues", "add health checks to containers", "set up a local dev environment with Docker", "create a multi-service setup", "debug container startup", "configure Docker volumes", "set up database containers", or mentions Dockerfile, Docker Compose, multi-stage builds, container images, build context, layer caching, ENTRYPOINT, CMD, docker-compose.yml, Docker health checks, or container orchestration for local development.

Ir para a instalação

Informações da origem

Repositório
jawwad-ali/claude-code-skills
Última atividade na origem
11 de março de 2026 às 18:35
Idioma detectado do SKILL.md
inglês
Estrelas
4
Forks
2

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Explorador de arquivos
7 arquivos

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
docker
description
This skill MUST be loaded when ANY Dockerfile, docker-compose.yml, docker-compose.override.yml, .dockerignore, or Docker-related configuration file is being read, reviewed, edited, or created. Also use when the user asks to "create a Dockerfile", "write a multi-stage build", "add a .dockerignore", "set up docker-compose", "containerize an application", "optimize a Docker image", "reduce Docker image size", "fix Docker build issues", "add health checks to containers", "set up a local dev environment with Docker", "create a multi-service setup", "debug container startup", "configure Docker volumes", "set up database containers", or mentions Dockerfile, Docker Compose, multi-stage builds, container images, build context, layer caching, ENTRYPOINT, CMD, docker-compose.yml, Docker health checks, or container orchestration for local development.
# Docker Development Guide This skill provides comprehensive guidance for writing production-ready Dockerfiles, .dockerignore files, and Docker Compose configurations for multi-service applications. ## Core Principles 1. **Ephemeral containers** — Containers can be stopped, destroyed, and replaced at any time. Never store state inside a container; use volumes or external services. 2. **Single process per container** — Each container runs one concern (API, frontend, database, cache). Compose or K8s orchestrates them together. 3. **Minimal surface area** — Use slim/alpine base images. Install only what the application needs. Remove build tools from runtime images via multi-stage builds. 4. **Layer caching matters** — Docker caches each instruction. Put the least-changing layers first (OS deps → app deps → app code). A single changed line invalidates all subsequent layers. 5. **Security by default** — Run as non-root, never bake secrets into layers, pin base image versions, scan for vulnerabilities. 6. **Reproducible builds** — Pin dependency versions (lockfiles), pin base image tags to minor versions (not `latest`), use `--frozen` / `--ci` flags for package managers. ## Dockerfile Fundamentals ### Base Image Selection | Use Case | Image | Why | |----------|-------|-----| | Python apps | `python:3.12-slim` | glibc-based (asyncpg/numpy work), smaller than full | | Node.js apps | `node:22-slim` | Consistent with CI, npm works natively | | Node.js (minimal) | `node:22-alpine` | Smallest Node image, good for simple apps | | Go apps | `golang:1.23` build → `gcr.io/distroless/static-debian12` run | Zero-dependency static binary | | Static files | `nginx:alpine` | Tiny, battle-tested web server | | PostgreSQL + pgvector | `pgvector/pgvector:pg16` | pgvector pre-installed, avoids manual extension setup | | Redis | `redis:7-alpine` | Minimal Redis with optional AOF persistence | **Why not alpine for Python?** Alpine uses musl libc. Packages like `asyncpg`, `numpy`, and `psycopg2` need glibc or require compilation from source, making builds slower and images potentially larger. Use `slim` (Debian-based, glibc) unless you have no C extensions. ### Instruction Reference **FROM** — Always pin to a specific minor version. Never use `latest` or bare major tags. ```dockerfile # Good FROM python:3.12-slim AS builder # Bad FROM python:latest FROM python:3 ``` **RUN** — Consolidate commands with `&&` to reduce layers. Clean up caches in the same layer they're created. ```dockerfile RUN apt-get update && \ apt-get install -y --no-install-recommends curl && \ rm -rf /var/lib/apt/lists/* ``` **COPY vs ADD** — Always use `COPY` unless you specifically need tar auto-extraction or remote URL fetching (rare). `COPY` is explicit and predictable. **ARG vs ENV** — `ARG` exists only during build (not in final image). `ENV` persists into running containers. Use `ARG` for build-time-only values like `NEXT_PUBLIC_API_URL`. ```dockerfile ARG NEXT_PUBLIC_API_URL=http://localhost:8000 ENV NODE_ENV=production ``` **EXPOSE** — Documentation only. Does not actually publish ports. Always pair with `-p` in `docker run` or `ports:` in Compose. **ENTRYPOINT vs CMD** — Use together: ENTRYPOINT for the executable, CMD for default arguments. Always use exec form (JSON array), not shell form. ```dockerfile # Correct: exec form — process gets PID 1, receives SIGTERM directly ENTRYPOINT ["uvicorn", "api.main:app"] CMD ["--host", "0.0.0.0", "--port", "8000"] # Wrong: shell form — wraps in /bin/sh, SIGTERM goes to shell not app ENTRYPOINT uvicorn api.main:app ``` **USER** — Always create and switch to a non-root user before CMD. ```dockerfile RUN groupadd -r app && useradd -r -g app -d /app -s /sbin/nologin app USER app ``` **WORKDIR** — Use absolute paths. Creates the directory if it doesn't exist. Prefer over `RUN mkdir`. **HEALTHCHECK** — Define health checks at the Dockerfile level. Works in standalone Docker, Compose, and K8s. ```dockerfile HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD curl -f http://localhost:8000/health || exit 1 ``` ### Multi-Stage Build Pattern The most important Docker pattern. Separates build-time dependencies (compilers, build tools) from runtime, producing minimal final images. ```dockerfile # Stage 1: Builder — has build tools, compiles dependencies FROM python:3.12-slim AS builder WORKDIR /app COPY pyproject.toml uv.lock ./ RUN pip install uv && uv sync --frozen --no-dev # Stage 2: Runtime — only the app and its runtime dependencies FROM python:3.12-slim AS runtime WORKDIR /app COPY --from=builder /app/.venv /app/.venv COPY . . ENV PATH="/app/.venv/bin:$PATH" USER app CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000"] ``` **Key insight**: The builder stage can be 500MB+ with gcc, make, and header files. The runtime stage copies only the compiled output, typically 100-200MB. For language-specific multi-stage patterns (Python/uv, Node.js/Next.js, Go), see `references/multi-stage-builds.md`. ## .dockerignore The `.dockerignore` file controls what Docker sends to the build daemon as "build context." Without it, Docker sends everything — including `.git/` (often 100MB+), `node_modules/`, `.venv/`, and secrets. **Place one `.dockerignore` per build context** — if your API and frontend have separate Dockerfiles with different build contexts, each needs its own `.dockerignore`. ### Python Project Template ``` .venv/ venv/ __pycache__/ *.pyc *.pyo *.egg-info/ dist/ build/ .git/ .env .env.* .vscode/ .idea/ *.md tests/ .coverage htmlcov/ .pytest_cache/ Dockerfile .dockerignore ``` ### Node.js Project Template ``` node_modules/ .next/ out/ .env .env.* .env.local coverage/ *.tsbuildinfo .vscode/ .idea/ *.md Dockerfile .dockerignore ``` ### Universal Exclusions (add to every .dockerignore) ``` .git/ .DS_Store Thumbs.db *.tmp *.swp *.log docker-compose*.yml k8s/ specs/ docs/ ``` ## Docker Compose Essentials ### Service Definition Pattern ```yaml services: api: build: context: . dockerfile: Dockerfile target: runtime # Select multi-stage target ports: - "8000:8000" environment: DATABASE_URL: postgresql://user:pass@postgres:5432/db REDIS_URL: redis://redis:6379 depends_on: postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped ``` ### depends_on with Health Checks The `condition: service_healthy` pattern ensures services start only after their dependencies are truly ready — not just running. ```yaml services: postgres: image: postgres:16 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 3s retries: 5 redis: image: redis:7-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 5 api: depends_on: postgres: condition: service_healthy redis: condition: service_healthy ``` ### Volumes **Named volumes** for data persistence (survives `docker compose down`): ```yaml services: postgres: volumes: - postgres_data:/var/lib/postgresql/data volumes: postgres_data: # Named volume — Docker manages the storage ``` **Bind mounts** for development hot-reload: ```yaml services: api: volumes: - ./api:/app/api # Source code mounted for live changes - ./agent:/app/agent ``` ### Environment Variables Three ways to inject env vars (in precedence order): 1. `environment:` — inline in compose file (good for non-sensitive defaults) 2. `env_file:` — load from a file (good for shared config) 3. Shell environment — `${VAR}` substitution from the host shell ```yaml services: api: env_file: .env # Load from file environment: OPENAI_MODEL: gpt-4o # Inline override DATABASE_URL: ${DATABASE_URL} # From host shell ``` ### Health Check Patterns by Service | Service | Health Check | |---------|-------------| | PostgreSQL | `pg_isready -U postgres` | | Redis | `redis-cli ping` | | HTTP API | `curl -f http://localhost:PORT/health \|\| exit 1` | | Next.js | `curl -f http://localhost:3000 \|\| exit 1` | ### Port Mapping ```yaml ports: - "8000:8000" # host:container — accessible from host machine expose: - "8000" # container only — accessible from other services, not host ``` ### Restart Policies | Policy | Use Case | |--------|----------| | `no` | Default. Don't restart. | | `unless-stopped` | Development — restarts on crash, stops with `docker compose stop` | | `always` | Production-like — always restarts, even after daemon restart | | `on-failure:3` | Restart up to 3 times on non-zero exit | ### Database Initialization Mount init scripts into PostgreSQL's entrypoint directory: ```yaml services: postgres: image: postgres:16 volumes: - postgres_data:/var/lib/postgresql/data - ./database/migrations/001_initial_schema.sql:/docker-entrypoint-initdb.d/001_schema.sql ``` Files in `/docker-entrypoint-initdb.d/` run automatically on first startup (when data volume is empty). Supports `.sql`, `.sql.gz`, and `.sh` files, executed in alphabetical order. For advanced Compose patterns (override files, profiles, init scripts, secrets, extension fields), see `references/compose-patterns.md`. ## Cross-Cutting Concerns ### Graceful Shutdown Containers receive `SIGTERM` on stop. The application must handle it to close connections cleanly. - **Always use exec form** for ENTRYPOINT/CMD — the process gets PID 1 and receives signals directly - Shell form (`ENTRYPOINT command arg`) wraps in `/bin/sh -c`, which may not forward signals - Python: uvicorn handles SIGTERM natively. Node.js: Next.js handles it. Go: use `signal.Notify` ### Health Check Portability The same health check concept works across all levels: - **Dockerfile**: `HEALTHCHECK` instruction - **Docker Compose**: `healthcheck:` in service definition - **Kubernetes**: `livenessProbe` and `readinessProbe` in pod spec Design health endpoints once (`/health/live`, `/health/ready`), use everywhere. ### Secrets Handling **Never do this:** ```dockerfile COPY .env /app/.env # Secret baked into image layer ARG OPENAI_API_KEY # Secret visible in build history ENV OPENAI_API_KEY=sk-... # Secret in image metadata ``` **Instead:** - Pass secrets at runtime via `environment:` or `env_file:` in Compose - Use `docker secret` for Swarm / `kubectl create secret` for K8s - For build-time secrets: `RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret` ### Logging Containers should log to stdout/stderr. The orchestrator (Docker, Compose, K8s) handles log collection, rotation, and forwarding. Never write logs to files inside the container. ## Best Practices 1. **Pin base image versions** to minor (`python:3.12-slim`, not `python:3-slim` or `latest`) 2. **Least-changing layers first** — OS deps → app deps (lockfile) → app source code 3. **Use .dockerignore** — exclude everything not needed in the image 4. **Run as non-root** — create a dedicated user, switch with `USER` 5. **One process per container** — orchestrate with Compose or K8s 6. **Multi-stage builds** — separate build-time from runtime dependencies 7. **Health checks everywhere** — Dockerfile, Compose, and K8s probes 8. **Never store secrets in layers** — pass at runtime, not build time 9. **Prefer COPY over ADD** — explicit and predictable 10. **Use exec form** for ENTRYPOINT/CMD — correct signal handling ## When to Read Reference Files | Need | File | |------|------| | Writing a Dockerfile for Python/uv, Node.js/Next.js, or Go | `references/multi-stage-builds.md` | | Advanced Compose: override files, profiles, init scripts, secrets | `references/compose-patterns.md` | | Build is slow, image is too large, need BuildKit features | `references/optimization.md` | ## Example Templates | Need | File | |------|------| | Python/FastAPI Dockerfile with uv | `examples/python-fastapi.Dockerfile` | | Node.js/Next.js Dockerfile with standalone output | `examples/node-nextjs.Dockerfile` | | Full-stack docker-compose.yml (API + frontend + DB + cache) | `examples/docker-compose-fullstack.yml` |
Ver no GitHub