Complete dockerfile toolkit with generation and validation capabilities
94
94%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advisory
Suggest reviewing before use
{
"instructions": [
{
"instruction": "Use specific version tags — NEVER use :latest as the base image tag",
"original_snippets": "Use specific version tags (NEVER use :latest)...FROM node:latest resolves to a different image on each build...GOOD: FROM node:20.18-alpine3.20",
"relevant_when": "Whenever writing any FROM instruction in a Dockerfile",
"why_given": "new knowledge"
},
{
"instruction": "Use multi-stage builds — separate build stage from runtime stage, keep build tools out of final image",
"original_snippets": "Multi-Stage Builds (REQUIRED for compiled languages, RECOMMENDED for all): Separate build stage from runtime stage. Keep build tools out of final image. Copy only necessary artifacts.",
"relevant_when": "When containerizing any application, especially compiled languages (Go, Java, TypeScript/Node.js builds)",
"why_given": "preference"
},
{
"instruction": "Run as non-root user — create a dedicated non-root user and use USER directive before CMD",
"original_snippets": "Run as non-root user (create dedicated user)...NEVER run containers as root...BAD: No USER instruction (defaults to root). GOOD: RUN addgroup -S appgroup && adduser -S appuser -G appgroup followed by USER appuser",
"relevant_when": "In every Dockerfile for any application",
"why_given": "new knowledge"
},
{
"instruction": "Use minimal base images (alpine, distroless) — not full OS images",
"original_snippets": "Use minimal base images (alpine, distroless)...Node.js: ~50-150MB with Alpine (vs ~1GB with full node image)...Go: ~5-20MB with distroless/scratch",
"relevant_when": "When choosing base images for any language",
"why_given": "preference"
},
{
"instruction": "Copy dependency files before application code (COPY package*.json ./ before COPY . .)",
"original_snippets": "Copy dependency files before application code...NEVER copy the entire build context before installing dependencies...BAD: COPY . . followed by RUN npm ci. GOOD: COPY package*.json ./ then RUN npm ci then COPY . .",
"relevant_when": "Whenever installing dependencies (npm, pip, go mod, maven, etc.)",
"why_given": "new knowledge"
},
{
"instruction": "Combine related RUN commands with && and clean up package manager caches in the same layer",
"original_snippets": "Combine related RUN commands with &&...Clean up package manager caches in same layer...NEVER split related package installation across multiple RUN layers...GOOD: RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*",
"relevant_when": "When writing RUN instructions that install system packages or dependencies",
"why_given": "new knowledge"
},
{
"instruction": "Use COPY not ADD when no archive extraction or URL fetch is needed",
"original_snippets": "NEVER use ADD when COPY is sufficient...ADD has implicit behaviors (auto-extracting tarballs, fetching URLs) that make Dockerfiles harder to reason about; COPY is explicit and predictable...BAD: ADD app.tar.gz /app/. GOOD: COPY app.tar.gz /app/",
"relevant_when": "Whenever copying files into the image",
"why_given": "new knowledge"
},
{
"instruction": "Add HEALTHCHECK for services",
"original_snippets": "Add HEALTHCHECK for services...Production Readiness (REQUIRED): Add HEALTHCHECK for services",
"relevant_when": "When containerizing long-running web services or APIs",
"why_given": "reminder"
},
{
"instruction": "Use exec form for ENTRYPOINT/CMD (JSON array syntax, not shell string)",
"original_snippets": "Use exec form for ENTRYPOINT/CMD...Production Readiness (REQUIRED): Use exec form for ENTRYPOINT/CMD",
"relevant_when": "When writing CMD or ENTRYPOINT instructions",
"why_given": "new knowledge"
},
{
"instruction": "Set WORKDIR to absolute paths",
"original_snippets": "Set WORKDIR to absolute paths...Production Readiness (REQUIRED): Set WORKDIR to absolute paths",
"relevant_when": "In any Dockerfile that sets a working directory",
"why_given": "reminder"
},
{
"instruction": "Document exposed ports with EXPOSE",
"original_snippets": "Document exposed ports with EXPOSE...Production Readiness (REQUIRED): Document exposed ports with EXPOSE",
"relevant_when": "When containerizing any network service that listens on a port",
"why_given": "reminder"
},
{
"instruction": "Always include syntax directive: # syntax=docker/dockerfile:1",
"original_snippets": "Always Include: Syntax directive: # syntax=docker/dockerfile:1",
"relevant_when": "In every Dockerfile generated",
"why_given": "preference"
},
{
"instruction": "Always create .dockerignore alongside the Dockerfile",
"original_snippets": "Always create .dockerignore with generated Dockerfile...Generate .dockerignore: Objective: Create comprehensive .dockerignore to reduce build context and prevent secret leaks.",
"relevant_when": "Every time a Dockerfile is generated",
"why_given": "new knowledge"
},
{
"instruction": ".dockerignore must exclude: .git, .env/.env.*, .github, Dockerfile*, docker-compose*.yml, node_modules/, IDE directories",
"original_snippets": "# Git .git .gitignore ... # Environment .env .env.* ... # Dependencies node_modules/ __pycache__/ ... # IDE .vscode/ .idea/",
"relevant_when": "When generating .dockerignore for any project",
"why_given": "new knowledge"
},
{
"instruction": "No hardcoded secrets in ENV instructions",
"original_snippets": "No hardcoded secrets...Security Hardening (REQUIRED): No hardcoded secrets",
"relevant_when": "When writing ENV instructions or handling environment variables",
"why_given": "reminder"
},
{
"instruction": "Order Dockerfile instructions from least to most frequently changing (for cache optimization)",
"original_snippets": "Order instructions from least to most frequently changing...Layer Optimization (REQUIRED): Order instructions from least to most frequently changing",
"relevant_when": "When structuring any Dockerfile's instruction sequence",
"why_given": "new knowledge"
},
{
"instruction": "Provide Optimization Metrics table in the final output (image size estimate, cache strategy, security summary)",
"original_snippets": "Optimization Metrics (REQUIRED - provide explicit estimates)...Always include a summary like this: | Metric | Estimate | | Image Size | ~150MB... | Build Cache | ... | Security | ...",
"relevant_when": "After generating any Dockerfile",
"why_given": "preference"
},
{
"instruction": "Provide Next Steps as a bulleted checklist after generation",
"original_snippets": "Next Steps (REQUIRED - always include as bulleted list)...Always provide explicit next steps: - [ ] Test the build locally...",
"relevant_when": "After delivering the final Dockerfile",
"why_given": "preference"
},
{
"instruction": "Gather requirements before generating (language/version, app type, framework, entry point, ports, env vars, health check)",
"original_snippets": "Stage 1: Gather Requirements...Information to Collect (use AskUserQuestion if missing or unclear): Language/version, application type, framework, entry point...Port(s), environment variables, config files, health check endpoint",
"relevant_when": "When the user's request is ambiguous or missing key details",
"why_given": "preference"
},
{
"instruction": "Always validate after generation using devops-skills:dockerfile-validator, and iterate at least once if errors are found",
"original_snippets": "Stage 5: Validate with devops-skills:dockerfile-validator...REQUIRED: Always validate after generation...Stage 6: Iterate on Validation Errors...REQUIRED: Iterate at least ONCE if validation finds errors",
"relevant_when": "After generating any Dockerfile",
"why_given": "preference"
}
]
}