DevOps essentials — Dockerfile best practices, CI/CD patterns, deployment configuration, and container security
89
87%
Does it follow best practices?
Impact
100%
1.21xAverage score across 3 eval scenarios
Passed
No known issues
{
"context": "Tests whether the agent proactively follows Dockerfile best practices when containerizing a Node.js API. The task only asks for a Dockerfile — it never mentions multi-stage builds, non-root users, layer ordering, or HEALTHCHECK. A production-ready Dockerfile should have all of these.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Multi-stage build",
"description": "Dockerfile uses at least two stages: a build stage that installs all dependencies and compiles TypeScript, and a production/runtime stage that contains only the compiled output and production dependencies. The production stage must not contain TypeScript compiler, dev dependencies, or source .ts files.",
"max_score": 15
},
{
"name": "Non-root user",
"description": "Production stage creates a non-root user (via adduser, addgroup, useradd, or equivalent) and includes a USER instruction to switch to that user. The container must not run as root.",
"max_score": 15
},
{
"name": ".dockerignore file created",
"description": "A .dockerignore file is created that excludes at minimum node_modules, .git, and .env files. Additional exclusions like dist, coverage, .vscode are good but not required.",
"max_score": 12
},
{
"name": "Cache-efficient layer ordering",
"description": "In the build stage, package.json and package-lock.json are copied BEFORE the rest of the source code, and npm install/npm ci runs between these two COPY steps. This ensures source code changes don't invalidate the dependency cache.",
"max_score": 12
},
{
"name": "HEALTHCHECK instruction",
"description": "Dockerfile includes a HEALTHCHECK instruction that probes the /health endpoint (or similar) with appropriate interval, timeout, and retries settings. Uses wget, curl, or a custom health check script.",
"max_score": 12
},
{
"name": "Specific base image tag",
"description": "FROM instructions use specific version tags (e.g., node:20-alpine, node:20-slim, node:22-alpine) rather than :latest or untagged node image.",
"max_score": 8
},
{
"name": "Alpine or slim base image",
"description": "Uses a minimal base image variant (alpine or slim) rather than the full Debian-based node image to reduce image size and attack surface.",
"max_score": 6
},
{
"name": "npm ci instead of npm install",
"description": "Uses npm ci (clean install) rather than npm install for reproducible, deterministic builds from the lockfile.",
"max_score": 5
},
{
"name": "NODE_ENV set to production",
"description": "NODE_ENV is set to 'production' in the production stage via ENV instruction.",
"max_score": 5
},
{
"name": "EXPOSE instruction present",
"description": "Dockerfile includes an EXPOSE instruction documenting the port the application listens on.",
"max_score": 5
},
{
"name": "WORKDIR set",
"description": "Both stages use WORKDIR to set a working directory rather than running commands in the root filesystem.",
"max_score": 5
}
]
}