Writing optimized, secure, multi-stage Dockerfiles with language-specific patterns (Python, Node.js, Go, Rust), BuildKit features, and distroless images. Use when containerizing applications, optimizing existing Dockerfiles, or reducing image sizes.
Create production-grade Dockerfiles with multi-stage builds, security hardening, and language-specific optimizations.
Invoke when:
Ask three questions to determine the approach:
1. What language?
references/python-dockerfiles.mdreferences/nodejs-dockerfiles.mdreferences/go-dockerfiles.mdreferences/rust-dockerfiles.mdreferences/java-dockerfiles.md2. Is security critical?
references/security-hardening.md)3. Is image size critical?
Separate build environment from runtime environment to minimize final image size.
Pattern:
# Stage 1: Build
FROM build-image AS builder
RUN compile application
# Stage 2: Runtime
FROM minimal-runtime-image
COPY --from=builder /app/binary /app/
CMD ["/app/binary"]
Benefits:
Decision matrix:
| Language | Build Stage | Runtime Stage | Final Size |
|----------|-------------|---------------|------------|
| Go (static) | golang:1.22-alpine | gcr.io/distroless/static-debian12 | 10-30MB |
| Rust (static) | rust:1.75-alpine | scratch | 5-15MB |
| Python | python:3.12-slim | python:3.12-slim | 200-400MB |
| Node.js | node:20-alpine | node:20-alpine | 150-300MB |
| Java | maven:3.9-eclipse-temurin-21 | eclipse-temurin:21-jre-alpine | 200-350MB |
Distroless images (Google-maintained):
gcr.io/distroless/static-debian12 → Static binaries (2MB)gcr.io/distroless/base-debian12 → Dynamic binaries with libc (20MB)gcr.io/distroless/python3-debian12 → Python runtime (60MB)gcr.io/distroless/nodejs20-debian12 → Node.js runtime (150MB)See references/base-image-selection.md for complete comparison.
Enable BuildKit for advanced caching and security:
export DOCKER_BUILDKIT=1
docker build .
# OR
docker buildx build .
Key features:
--mount=type=cache → Persistent package manager caches--mount=type=secret → Inject secrets without storing in layers--mount=type=ssh → SSH agent forwarding for private reposSee references/buildkit-features.md for detailed patterns.
Order Dockerfile instructions from least to most frequently changing:
# 1. Base image (rarely changes)
FROM python:3.12-slim
# 2. System packages (rarely changes)
RUN apt-get update && apt-get install -y build-essential
# 3. Dependencies manifest (changes occasionally)
COPY requirements.txt .
RUN pip install -r requirements.txt
# 4. Application code (changes frequently)
COPY . .
# 5. Runtime configuration (rarely changes)
CMD ["python", "app.py"]
BuildKit cache mounts:
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
Cache persists across builds, eliminating redundant downloads.
Essential security practices:
1. Non-root users
# Debian/Ubuntu
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser
# Alpine
RUN adduser -D -u 1000 appuser && chown -R appuser:appuser /app
USER appuser
# Distroless (built-in)
USER nonroot:nonroot
2. Secret management
# ❌ NEVER: Secret in layer history
RUN git clone https://${GITHUB_TOKEN}@github.com/private/repo.git
# ✅ ALWAYS: BuildKit secret mount
RUN --mount=type=secret,id=github_token \
TOKEN=$(cat /run/secrets/github_token) && \
git clone https://${TOKEN}@github.com/private/repo.git
Build with:
docker buildx build --secret id=github_token,src=./token.txt .
3. Vulnerability scanning
# Trivy (recommended)
trivy image myimage:latest
# Docker Scout
docker scout cves myimage:latest
4. Health checks
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
See references/security-hardening.md for comprehensive hardening patterns.
Create .dockerignore to exclude unnecessary files:
# Version control
.git
.gitignore
# CI/CD
.github
.gitlab-ci.yml
# IDE
.vscode
.idea
# Testing
tests/
coverage/
**/*_test.go
**/*.test.js
# Build artifacts
node_modules/
dist/
build/
target/
__pycache__/
# Environment
.env
.env.local
*.log
Reduces build context size and prevents leaking secrets.
Three approaches:
Example: Poetry multi-stage
FROM python:3.12-slim AS builder
RUN --mount=type=cache,target=/root/.cache/pip \
pip install poetry==1.7.1
COPY pyproject.toml poetry.lock ./
RUN poetry export -f requirements.txt --output requirements.txt
RUN --mount=type=cache,target=/root/.cache/pip \
python -m venv /opt/venv && \
/opt/venv/bin/pip install -r requirements.txt
FROM python:3.12-slim
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
USER 1000:1000
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]
See references/python-dockerfiles.md for complete patterns and examples/python-fastapi.Dockerfile.
Key patterns:
npm ci (not npm install) for reproducible buildsnode user (UID 1000)Example: Express multi-stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
npm ci
COPY . .
RUN npm run build
RUN npm prune --omit=dev
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
USER node
CMD ["node", "dist/index.js"]
See references/nodejs-dockerfiles.md for npm/pnpm/yarn patterns and examples/nodejs-express.Dockerfile.
Smallest possible images:
-ldflags="-s -w"/go/pkg/mod and build cacheExample: Distroless static
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
go mod download
COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o main .
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/main /app/main
USER nonroot:nonroot
ENTRYPOINT ["/app/main"]
See references/go-dockerfiles.md and examples/go-microservice.Dockerfile.
Ultra-small static binaries:
Example: Scratch base
FROM rust:1.75-alpine AS builder
RUN apk add --no-cache musl-dev
WORKDIR /app
# Cache dependencies
COPY Cargo.toml Cargo.lock ./
RUN --mount=type=cache,target=/usr/local/cargo/registry \
mkdir src && echo "fn main() {}" > src/main.rs && \
cargo build --release --target x86_64-unknown-linux-musl && \
rm -rf src
# Build application
COPY src ./src
RUN --mount=type=cache,target=/usr/local/cargo/registry \
cargo build --release --target x86_64-unknown-linux-musl
FROM scratch
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/app /app
USER 1000:1000
ENTRYPOINT ["/app"]
See references/rust-dockerfiles.md and examples/rust-actix.Dockerfile.
BuildKit cache mount locations:
| Language | Package Manager | Cache Mount Target |
|----------|----------------|-------------------|
| Python | pip | --mount=type=cache,target=/root/.cache/pip |
| Python | poetry | --mount=type=cache,target=/root/.cache/pypoetry |
| Python | uv | --mount=type=cache,target=/root/.cache/uv |
| Node.js | npm | --mount=type=cache,target=/root/.npm |
| Node.js | pnpm | --mount=type=cache,target=/root/.local/share/pnpm/store |
| Go | go mod | --mount=type=cache,target=/go/pkg/mod |
| Rust | cargo | --mount=type=cache,target=/usr/local/cargo/registry |
Persistent caches eliminate redundant package downloads across builds.
Validate Dockerfile quality:
# Lint Dockerfile
python scripts/validate_dockerfile.py Dockerfile
# Scan for vulnerabilities
trivy image myimage:latest
# Analyze image size
docker images myimage:latest
docker history myimage:latest
Compare optimization results:
# Before optimization
docker build -t myapp:before .
# After optimization
docker build -t myapp:after .
# Compare
bash scripts/analyze_image_size.sh myapp:before myapp:after
See scripts/validate_dockerfile.py for automated Dockerfile linting.
Upstream (provide input):
testing-strategies → Test application before containerizingsecurity-hardening → Application-level security before Docker layerDownstream (consume Dockerfiles):
building-ci-pipelines → Build and push Docker images in CIkubernetes-operations → Deploy containers to K8s clustersinfrastructure-as-code → Deploy containers with Terraform/PulumiParallel (related context):
secret-management → Inject runtime secrets (K8s secrets, vaults)observability → Container logging and metrics collection1. Static binary (Go/Rust) → Smallest image
gcr.io/distroless/static-debian12 or scratch2. Interpreted language (Python/Node.js) → Production-optimized
3. JVM (Java) → Optimized runtime
4. Security-critical → Maximum hardening
5. Development → Fast iteration
❌ Never:
latest tags (unpredictable builds)✅ Always:
python:3.12.1-slim, not python:3)Base image registries:
gcr.io/distroless/*python:*, node:*, golang:*registry.access.redhat.com/ubi9/*Vulnerability scanners:
trivy image myimage:latestdocker scout cves myimage:latestgrype myimage:latestReference documentation:
references/base-image-selection.md → Complete base image comparisonreferences/buildkit-features.md → Advanced BuildKit patternsreferences/security-hardening.md → Comprehensive security guidereferences/ directoryexamples/ directorynpx skills add ancoleman/writing-dockerfiles下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer