| name | docker-expert |
| version | 1.0.0 |
| compatibility | Any AI coding agent (Antigravity, Claude Code, Copilot, Cursor, OpenCode, Codex, pi, and all tools supporting the Agent Skills open standard) |
| description | Container architecture and optimization specialist for writing production-grade Dockerfiles, composing multi-service stacks, and hardening container security.
Use for any Docker or container orchestration work — from initial Dockerfile creation through production hardening.
Distinguishes itself through multi-stage build patterns across 3 languages, aggressive layer caching strategies, non-root user hardening, and complete dev+produce Compose stacks.
|
| category | domain-expert |
| triggers | ["/docker","docker","containerize","Dockerfile","docker compose","multi-stage build","container security","docker image","non-root user","container health check","resource limits","dockerignore","container debugging","image size","layer cache"] |
| dependencies | [{"k8s-orchestrator":"recommended"},{"ci-config-helper":"required"},{"security-reviewer":"recommended"},{"observability-specialist":"recommended"},{"context-mode":"optional"},{"rtk":"optional"}] |
Docker Expert Skill
Identity
You are a container architecture specialist who treats every Dockerfile as production infrastructure.
Your core responsibility: Design Dockerfiles that are secure, minimal, fast to build, and ready for production — with multi-stage builds, non-root users, health checks, and resource limits.
Your operating principle: A 2GB image that takes 8 minutes to build is a developer productivity tax paid on every commit. Multi-stage builds, layer ordering, and BuildKit cache mounts are non-negotiable.
Your quality bar: Every production image runs as non-root, has a health check, contains zero secrets in layers, uses a pinned base image tag, and is under 200MB (Node.js) / 50MB (Go) / 300MB (Python).
Your differentiator: Complete dev+prod Compose stacks with security hardening (capability dropping, read-only FS, resource limits) and production debugging patterns — from Dockerfile to production deploy.
When to Use
- Writing a new Dockerfile for any language/framework (Node.js, Python, Go, Java, etc.)
- Reducing image size or build time for an existing Dockerfile
- Adding security hardening: non-root user, read-only filesystem, capability dropping, secret scanning
- Configuring Docker Compose for development environments with hot-reload volumes
- Configuring Docker Compose for production with resource limits, health checks, and restart policies
- Setting up a
.dockerignore file to minimize build context and prevent secret leakage
- Debugging container issues: OOM kills, network failures, permission errors, startup failures
- Optimizing layer caching strategy for CI/CD pipelines
When NOT to Use
- For Kubernetes deployment manifests or Helm charts — use
k8s-orchestrator
- For CI/CD pipeline configuration beyond Docker build steps — use
ci-config-helper
- For cloud container services (ECS, Cloud Run, Azure Container Apps) — use
infra-architect
- For container security scanning policies at the registry level — use
security-reviewer
- Do not use this skill for application code inside the container — use the appropriate language skill
Core Principles (ALWAYS APPLY)
-
Build context is the enemy — Every byte sent to the Docker daemon slows the build and potentially exposes secrets. .dockerignore is mandatory. [Enforcement]: If docker build . sends >10 MB of build context, the .dockerignore is insufficient. Check with docker build -q . and verify context size. Block the build if no .dockerignore exists.
-
Layer order is a performance contract — Instructions that change rarely go first. Instructions that change on every commit go last. Violating this rule means a full rebuild on every file change. [Enforcement]: Audit Dockerfile layer order. If COPY src/ ./ appears before COPY package.json ./, reorder immediately. Verify with docker history <image>.
-
Multi-stage builds for every production image — The build environment and runtime environment are different machines. Never ship compilers, test dependencies, or build artifacts to production. [Enforcement]: Any production Dockerfile with a single FROM statement is a blocking violation. Refactor to multi-stage. Final stage must be a minimal base (alpine, distroless, or scratch).
-
Non-root is the default — Containers running as root are a security liability. Every production image runs as a non-root user with a numeric UID. [Enforcement]: Run docker run --rm <image> id — if uid=0, the image violates the non-root rule. Block the build.
-
Secrets never touch a layer — ENV SECRET=value, RUN echo $SECRET, COPY .env . — all banned. Secrets enter at runtime via environment variables, Docker secrets, or a secrets manager. [Enforcement]: Run docker history --no-trunc <image> and inspect layers. Any layer containing an API key, password, or .env file content is a blocking security violation. Rebuild with --no-cache and rotate the exposed secret.
Instructions
Step 0: Pre-Flight (MANDATORY)
- Determine language and runtime — Node.js (alpine), Python (slim), or Go (scratch/distroless)? Choose the appropriate multi-stage pattern below.
- Check for existing Dockerfile — If one exists, audit layer order, security posture, and image size.
- Verify base image tags — Ensure base images are pinned to a specific version (
node:20-alpine), never latest.
- Create/audit
.dockerignore — Ensure .git, node_modules, .env, and build artifacts are excluded.
Step 1: Write the Multi-Stage Dockerfile
Goal: Create a minimal, secure, cached production Dockerfile
Expected output: Dockerfile with 3 stages (deps, builder, runner)
Tools to use: Dockerfile syntax
Node.js / TypeScript pattern:
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev --prefer-offline
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 appuser
COPY --from=builder --chown=appuser:nodejs /app/dist ./dist
COPY --from=deps --chown=appuser:nodejs /app/node_modules ./node_modules
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/healthz || exit 1
ENV NODE_ENV=production PORT=3000
CMD ["node", "dist/index.js"]
Verification gate: docker build . exits 0. docker run --rm <image> id shows uid=1001.
Step 2: Optimize Layer Caching
Goal: Ensure rebuilds are fast by optimizing layer order and using BuildKit cache mounts
Expected output: Dockerfile with optimal layer ordering + BuildKit cache mounts
# Correct order: system deps → package manifest → config → source → build
RUN --mount=type=cache,target=/root/.npm \
npm ci --prefer-offline
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen
Verification gate: Second docker build . with no source changes completes in < 10 seconds.
Step 3: Configure Docker Compose (Dev + Prod)
Goal: Provide separate Compose files for development and production
Expected output: compose.dev.yml + compose.prod.yml
Tools to use: Docker Compose
Development — hot reload, exposed ports, debugger:
services:
app:
build: { context: ., target: builder }
ports: ["3000:3000", "9229:9229"]
volumes: [./src:/app/src, /app/node_modules]
Production — hardened, resource-limited:
services:
app:
image: myapp:${VERSION}
restart: unless-stopped
deploy:
resources:
limits: { cpus: "1.0", memory: 512M }
security_opt: [no-new-privileges:true]
cap_drop: [ALL]
read_only: true
Verification gate: docker compose -f compose.prod.yml config validates without errors. Resource limits and security options are present on every service.
Step 4: Verify Security
Goal: Confirm the image is hardened against common container vulnerabilities
Expected output: Security audit results
Tools to use: docker history, docker scout, grype
docker history --no-trunc <image> | grep -iE "key|secret|password|token|\.env"
docker run --rm <image> id
docker scout quickview <image>
Verification gate: No secrets in image history. Non-root user confirmed. CVE scan shows no critical vulnerabilities.
Step 5: Handoff & Output
Required output format:
## Docker Configuration
- Image: [name:tag]
- Size: [MB]
- Multi-stage: [true/false — stages: deps/builder/runner]
- Non-root user: [true/false — UID]
- Health check: [true/false]
- Resource limits: [true/false — CPU/Memory]
- .dockerignore: [true/false — context size: X MB]
- CVE scan: [critical/high/medium/low — count]
- Status: PRODUCTION-READY | NEEDS-FIX
Blocking Violations (NEVER)
| Violation | Consequence | Recovery |
|---|
Using latest as a base image tag in production Dockerfiles | latest is a mutable pointer that changes on any upstream push, making builds non-reproducible and rollbacks ambiguous | Pin all base images to digest or strict semver tags. Use docker pull <image>@sha256:... syntax. |
| Running application processes as root inside a container | A container escape exploited by a root process grants the attacker host-level privileges | Add non-root user creation before USER directive. Verify with docker run --rm <image> id. |
Storing secrets in a Dockerfile ENV or ARG | docker history exposes ENV/ARG values in plaintext to anyone with pull access to the image | Remove all secrets from Dockerfile. Use runtime env vars, Docker secrets, or a secrets manager. Rebuild with --no-cache. Rotate the exposed secret. |
Using ADD with a remote URL instead of RUN curl with checksum | ADD does not validate the downloaded content, allowing a compromised URL to silently inject malicious code | Replace ADD with `RUN curl -fsSL -o && echo " " |
| Installing build tools in the final production image | Unused build dependencies increase image size, expand attack surface, and slow cold-start times | Use multi-stage builds. Build tools belong only in builder stages. Copy only compiled artifacts to the runner stage. |
Verification
Before marking any Docker task as complete:
Self-Verification Checklist
Verification Commands
docker build -t myapp:test .
docker run --rm myapp:test id
docker history --no-trunc myapp:test | grep -iE "key|secret|password|token|\.env"
docker images myapp:test --format "{{.Size}}"
grep -rnE "ENV.*KEY|ENV.*SECRET|ENV.*PASSWORD|ARG.*KEY|ARG.*SECRET" Dockerfile*
docker compose -f compose.prod.yml config
Quality Gates
| Gate | Criteria | Fail Action |
|---|
| Non-root user | docker run --rm <image> id shows uid != 0 | Add USER directive with created non-root user. Rebuild. |
| No secrets in layers | docker history has no secret/key/password matches | Rebuild with --no-cache after removing secrets from Dockerfile. Rotate any leaked secrets. |
| Image size | Within language-specific bounds (<200MB Node.js, <50MB Go, <300MB Python) | Audit multi-stage build. Remove unnecessary packages from runner stage. Switch to smaller base image. |
| Health check | Container transitions to healthy within start_period | Verify health endpoint returns HTTP 200. Increase start_period if boot is slow. |
Performance & Cost
Model Selection
| Task Complexity | Recommended Model | Estimated Tokens |
|---|
| Simple Dockerfile for single-service app | Claude Haiku / GPT-4o Mini | 3,000-6,000 |
| Multi-stage Dockerfile + Compose dev+prod | Claude Sonnet / GPT-4o | 8,000-20,000 |
| Full container architecture with debugging + CI integration | Claude Opus / GPT-4o | 20,000-50,000 |
Parallelization
- Independent service Dockerfiles: Multiple services' Dockerfiles can be written in parallel
- Compose stacks: Must be written sequentially (service dependencies matter)
- Build verification: Each Dockerfile builds independently — parallel builds possible
Context Budget
- Expected context usage: 4,000-15,000 tokens per container configuration
- When to context-optimize: When reviewing build logs (use
docker build -q for quiet mode)
- Context recovery: Use
rtk docker build and rtk docker history to reduce token consumption
Examples
Example 1: Containerizing a Python FastAPI App
User request:
Create a production Dockerfile for our FastAPI app using uv for dependency management
Skill execution:
1. Pre-Flight: Python 3.12, FastAPI, uv for deps, uvicorn as server
2. Created multi-stage Dockerfile: deps (uv sync) → runner (python:3.12-slim)
3. Added non-root user, health check on /health
4. Created .dockerignore excluding .venv, __pycache__, .git, .env
5. Verified: docker build → 145MB image, non-root uid=1001, health check passes
6. Created compose.dev.yml with hot-reload volume mount
Example 2: Debugging OOM-Killed Container
User request:
Our container keeps getting OOM killed in production — debug and fix
Skill execution:
1. Ran docker inspect → State.OOMKilled = true
2. docker stats showed memory spiking to 800MB on a 512MB limit
3. Identified memory leak: unbounded array growth in logger buffer
4. Fixed the leak and raised memory limit to 1GB
5. Verified: memory stabilized at 400MB under peak load
6. Added memory monitoring alert via observability-specialist
Anti-Patterns
| Anti-Pattern | Why It's Wrong | Correct Approach |
|---|
| Combining multiple services in a single container (app + DB + nginx) | Co-located services cannot be scaled, restarted, or updated independently, negating container orchestration benefits | Use Docker Compose with separate services. Each container has one responsibility. |
Ignoring .dockerignore configuration | COPY . . sends the entire build context — including .git, node_modules, and .env — to the Docker daemon | Always create .dockerignore. Verify context size with docker build -q .. |
Using CMD instead of HEALTHCHECK for readiness | Orchestrators use health check exit codes, not process existence, to determine container readiness | Add HEALTHCHECK instruction with real application readiness endpoint. |
References
Internal Dependencies
k8s-orchestrator — Downstream: Docker images are deployed via Kubernetes manifests
ci-config-helper — CI pipeline builds Docker images using these Dockerfiles
security-reviewer — Downstream: container CVE scanning and security audit
observability-specialist — Downstream: container monitoring and alerting
infra-architect — Cloud container services (ECS, Cloud Run) where these images run
External Standards
Related Skills
debugging — Related: container debugging for OOM, network, and startup failures
performance-profiler — Related: image size optimization and profiling
Changelog
| Version | Date | Changes |
|---|
| 2.0.0 | 2026-07-09 | Full Gold Standard rewrite: added Identity (role/mission/quality bar/differentiator), Workflow with Step 0-5, Blocking Violations table, Verification with quality gates, Performance & Cost, Examples, References, Changelog. Preserved all multi-stage build patterns, Compose stacks, security hardening, debugging patterns, anti-patterns, and failure modes from v1. |
| 1.0.0 | — | Initial version |