Design, review, and optimize Dockerfiles, Docker images, and Docker Compose configurations for production, performance, and maintainability. Use when auditing Docker configurations, creating production-ready images, designing multi-container architectures, or implementing container orchestration with focus on security, reproducibility, minimal attack surface, build optimization, and observability.
Instalación
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Design, review, and optimize Dockerfiles, Docker images, and Docker Compose configurations for production, performance, and maintainability. Use when auditing Docker configurations, creating production-ready images, designing multi-container architectures, or implementing container orchestration with focus on security, reproducibility, minimal attack surface, build optimization, and observability.
Docker Best Practices
Overview
This skill guides you through designing and optimizing Docker configurations with a focus on:
Production readiness: Security, reproducibility, observability
Performance: Build time optimization, minimal image size
Maintainability: Clear structure, consistency, clean separation of concerns
Targeted at backend developers and DevOps engineers deploying containerized services (Python/FastAPI, Node.js, Go) to Docker/Kubernetes environments.
When to Use This Skill
Activate when users:
Ask to review or optimize a Dockerfile or Docker Compose configuration
Want "best practices" for images, builds, or deployments
Question multi-stage builds, base image selection, or .dockerignore strategy
Need examples for containerized backend + database setups
Build command defaults: prefer Docker Buildx over legacy docker build
Balance conciseness with depth:
Start with a checklist summary
Detail with concrete examples (Dockerfile, compose.yml)
Point toward idiomatic code aligned with clean architecture (app logic separated from infrastructure)
Avoid anti-patterns explicitly:
Explain why something is problematic (security, performance, debugging)
Propose a clear, immediately actionable alternative
Treat legacy docker build usage as an anti-pattern when Buildx is expected
Build command policy:
Use docker buildx build as the default command in examples and recommendations.
For local image usage after build, prefer docker buildx build --load -t <tag> ..
If Buildx is not installed, instruct to install/enable Buildx before proceeding.
Key Docker Image Practices
Minimal Base Images
Compiled languages (Go, Rust): Use distroless or scratch for runtime when possible—reduces attack surface and image size dramatically.
Interpreted languages (Node, Python): Prefer -alpine or -slim variants for production unless specific compatibility issues exist (e.g., glibc requirements on Alpine).
Example (Python):
FROM python:3.12-slim
Multi-Stage Builds with uv (Standard Pattern)
Always use uv via the official Astral binary image. Never use pip or requirements.txt in this project.
The pattern: install deps into an isolated .venv in builder, then copy only the .venv folder to runtime. The --mount=type=cache keeps the uv cache outside the final image layers.
# BUILDER STAGE
FROM python:3.12-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
# uv env vars: pre-compile bytecode, use copy mode (required for mount caches)
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
WORKDIR /app
# 1. Install dependencies first — this layer is cached until pyproject.toml or uv.lock changes
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen --no-install-project --no-dev
# 2. Copy source and install the project itself
COPY src/ ./src/
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev
# RUNTIME STAGE
FROM python:3.12-slim AS runtime
WORKDIR /app
# Copy venv (with pre-compiled bytecode) and source from builder
COPY --from=builder /app/.venv /app/.venv
COPY src/ ./src/
# Place venv binaries first in PATH
ENV PATH="/app/.venv/bin:$PATH"
RUN useradd -m appuser && chown -R appuser /app
USER appuser
CMD ["uvicorn", "src.web.main:app", "--host", "0.0.0.0", "--port", "8000"]
Why .venv copy instead of global site-packages: copying the whole /app/.venv folder between stages is explicit, avoids polluting the system Python, and requires no knowledge of the Python minor version path.
Layer Caching Optimization
Order layers by change frequency: rarely-changed to frequently-changed. With uv, split the sync into two steps to protect the dependency cache from source code churn:
# Step 1: sync deps only (cached until pyproject.toml or uv.lock change)
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen --no-install-project --no-dev
# Step 2: copy source, then install the project (invalidated on code change only)
COPY src/ ./src/
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev
The --mount=type=cache is ephemeral — it does not land in the final image layer, so there is no need to manually purge uv's cache.
Reduce Layer Count
Combine related RUN commands in a single instruction, cleaning up in the same step:
# Better than separate RUN commands
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl git \
&& rm -rf /var/lib/apt/lists/*
Explicit Copying and .dockerignore
Use .dockerignore aggressively to exclude non-essential files:
Create a dedicated application user and run the container as that user:
RUN useradd -m appuser && chown -R appuser /app
USER appuser
Pattern: Root owns binaries and code (read-only), application user executes only.
Pin Base Image Versions
Never use latest; pin to major.minor at minimum, consider patch for maximum reproducibility:
FROM python:3.12-slim # Better than python:latest
# OR for reproducibility
FROM python:3.12.1-slim@sha256:abc123...
Minimize "Attacker Toolkit"
Avoid including debugging tools (curl, wget, nc) unless necessary. For debugging, use ephemeral containers attached to the network:
docker run --rm -it --network app-network nicolaka/netshoot
Secret Management
Never:
ENV API_KEY=secret in Dockerfile
Copy .env files into image
Hardcode tokens or credentials
Do:
Inject secrets at runtime via environment variables
Use orchestrator secrets (Kubernetes, Docker Swarm)
For advanced builds: use BuildKit secrets (RUN --mount=type=secret=...)
Performance Optimization
Build Time
Layer caching: Order Dockerfile to cache frequently-used layers early
.dockerignore: Reduce build context size
CI caching: Cache layers in registry, reuse across builds
Image Size
Multi-stage builds (builder vs. runtime)
Use --mount=type=cache,target=/root/.cache/uv — cache is ephemeral and never written into an image layer, so there is nothing to clean up manually
UV_COMPILE_BYTECODE=1 pre-compiles .pyc files at build time, reducing cold-start overhead
Drop dev dependencies with --no-dev in the uv sync runtime call
Use distroless or -slim base images
Vulnerability Scanning
Integrate tools into CI pipeline (Trivy, Docker Scout, Grype) without requiring detailed setup in the skill—mention as part of the production pipeline.