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
This skill validates Dockerfiles using a single self-contained script (dockerfile-validate.sh) that handles everything: tool installation, validation, and cleanup.
Key Features:
Single command to validate any Dockerfile:
bash scripts/dockerfile-validate.sh DockerfileThe script automatically checks for hadolint and Checkov, installs them temporarily in Python venvs if needed, runs all 4 validation stages, then cleans up on exit.
The dockerfile-validate.sh script runs a comprehensive 4-stage validation:
Workflow:
# Run hadolint on Dockerfile
hadolint Dockerfile
# Run with JSON output for parsing
hadolint --format json Dockerfile
# Run with specific rules ignored
hadolint --ignore DL3006 --ignore DL3008 Dockerfile
# Using Docker if not installed
docker run --rm -i hadolint/hadolint < DockerfileFor the full list of DL-prefixed (hadolint) and SC-prefixed (ShellCheck) rules, see references/docker_best_practices.md.
Rule Severity Levels: error → warning → info → style
Best Practices:
.hadolint.yaml for project-specific rulesInstallation (permanent):
pip3 install checkov # direct
brew install checkov # macOSWorkflow:
# Scan a Dockerfile
checkov -f Dockerfile --framework dockerfile
# Scan a directory (finds all Dockerfiles)
checkov -d . --framework dockerfile
# Compact output (failures only)
checkov -f Dockerfile --framework dockerfile --compact
# Skip specific checks
checkov -f Dockerfile --framework dockerfile --skip-check CKV_DOCKER_2For the full list of CKV_DOCKER_* security checks, see references/security_checklist.md.
Suppressing False Positives:
# checkov:skip=CKV_DOCKER_2:Health check not applicable for this init container
FROM alpine:3.21Best Practices:
Custom Validation Checks:
# Check for :latest tag usage
grep -E "^FROM.*:latest" Dockerfile
# Count FROM statements (single FROM = multi-stage opportunity)
grep -c "^FROM" Dockerfile
# Ensure USER is set before CMD/ENTRYPOINT
grep "^USER" Dockerfile
# Verify HEALTHCHECK is defined for services
grep "^HEALTHCHECK" Dockerfile
# Count RUN commands (>5 suggests combination opportunity)
grep -c "^RUN" Dockerfile
# Verify cache cleanup in same RUN layer
grep "rm -rf /var/lib/apt/lists" Dockerfile
grep "--no-cache" Dockerfile # for apkNon-Obvious Checks (project-specific):
| Category | Non-Obvious Convention |
|---|---|
| Base Images | Prefer digest pinning (FROM alpine@sha256:…) over version tags for reproducible builds |
| Layer Ordering | COPY dependency manifests before source code so edits don't bust the install cache |
| Cache Cleanup | Must happen in the same RUN layer as the install; a separate RUN rm -rf … creates a new layer that doesn't reduce size |
| Multi-Stage | Named stages (AS build) allow selective --target build for CI debugging without exposing secrets in final image |
| Secrets | BuildKit --mount=type=secret avoids secrets ever appearing in any layer, including intermediate ones |
Optimization Categories:
Image Size Reduction:
# Bad: Full distro
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curl
# Good: Minimal distro
FROM alpine:3.21
RUN apk add --no-cache curl
# Better: Multi-stage with distroless
FROM golang:1.21 AS build
WORKDIR /app
COPY . .
RUN go build -o myapp
FROM gcr.io/distroless/base-debian11
COPY --from=build /app/myapp /
ENTRYPOINT ["/myapp"]Layer Optimization:
# Bad: Separate RUN commands (creates many layers)
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y git
# Good: Combined RUN (single layer)
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
git \
&& rm -rf /var/lib/apt/lists/*Build Cache Efficiency:
# Bad: Copy all, then install dependencies
COPY . /app
RUN pip install -r requirements.txt
# Good: Copy dependency file first
COPY requirements.txt /app/
RUN pip install -r requirements.txt
COPY . /app# Check if .dockerignore exists
if [ ! -f .dockerignore ]; then
echo "WARNING: .dockerignore file not found"
fiCommon patterns to include:
.git
.gitignore
.env
*.log
node_modules
Dockerfile*
docker-compose*.ymlThe validation script automatically installs tools if not found. No manual installation required.
For permanent installations:
# hadolint
brew install hadolint # macOS
wget -O ~/.local/bin/hadolint https://github.com/hadolint/hadolint/releases/latest/download/hadolint-Linux-x86_64 && chmod +x ~/.local/bin/hadolint # Linux
# Checkov
pip3 install checkovMinimum Versions: hadolint >= 2.12.0 | Checkov: latest | Python >= 3.8
Testing Auto-Install:
# Force temporary installation for testing
FORCE_TEMP_INSTALL=true bash scripts/dockerfile-validate.sh DockerfileWhen tools are not installed, the script auto-installs them temporarily. If auto-install fails:
brew install hadolint (macOS) or wget from GitHub releases (Linux)pip3 install checkovTool Priority:
| Error | Solution |
|---|---|
FROM instruction must be first non-comment | Move ARG VERSION=18 before FROM node:${VERSION} |
| Unknown instruction (typo) | Check spelling: common typos are RUNS, COPIES, FRUM |
| Chained RUN command fails | Use apt-get install -y package || exit 1 or set -e |
COPY failed: file not found | Check path is relative to build context; verify not excluded by .dockerignore |
| Hardcoded secrets detected | Use BuildKit secrets: docker build --secret id=api_key,src=api_key.txt instead of ENV API_KEY=secret123 |
| Slow builds | Optimize layer caching (COPY package files first), use .dockerignore, enable BuildKit (export DOCKER_BUILDKIT=1), use multi-stage builds |
Follow these steps in order for every validation request:
bash scripts/dockerfile-validate.sh <Dockerfile> to run all 4 stages.Summarize findings by severity:
Propose specific fixes — Use the Read tool to load appropriate reference files before proposing fixes:
| Issue Type | Reference File |
|---|---|
| Security issues (secrets, USER, ports) | references/security_checklist.md |
| Size/performance optimization | references/optimization_guide.md |
| General best practices | references/docker_best_practices.md |
Offer to apply fixes — Ask the user if they want fixes applied, then apply if approved.
Example interaction:
User: "Validate my Dockerfile"
1. Read the Dockerfile using Read tool
2. Run: bash scripts/dockerfile-validate.sh Dockerfile
3. Review output from all 4 stages
4. Summarize findings by severity (critical → low)
5. Use Read tool to load relevant reference files:
- Read references/security_checklist.md (if security issues found)
- Read references/optimization_guide.md (if optimization issues found)
- Read references/docker_best_practices.md (if best practice issues found)
6. Propose specific fixes with code examples from reference content
7. Ask: "Would you like me to apply these fixes?"
8. Apply fixes if user approvesFor multi-Dockerfile projects: find all Dockerfile* files, validate each sequentially, aggregate results, and provide a unified report with project-wide improvement suggestions.
docker build exits 0.hadolint Dockerfile in CI as a required check; treat W rules as warnings and DL rules as errors.DL3008 (unpinned apt packages)RUN apt-get install -y curlRUN apt-get install -y curl=7.88.1-* or use a digest-pinned base image with pre-installed versions.trivy image myapp:latest after build in the CI pipeline.--no-cache as a security measure--no-cache prevents layer caching during the current build but does not remove vulnerabilities in the base image or installed packages; image scanning is still required.--no-cache to ensure a "fresh" secure image.--no-cache for reproducibility in CI; pair with image scanning for security assurance.Internal:
bash scripts/dockerfile-validate.sh [Dockerfile]| File | Purpose |
|---|---|
good-example.Dockerfile | Best practices and optimal structure |
bad-example.Dockerfile | Common mistakes and anti-patterns |
security-issues.Dockerfile | Intentional security vulnerabilities for testing |
python-optimized.Dockerfile | Python-specific optimizations and multi-stage build |
golang-distroless.Dockerfile | Minimal Go application using distroless base image |
.dockerignore.example | Example .dockerignore for build context optimization |
| File | Contents |
|---|---|
docker_best_practices.md | Official Docker best practices; full hadolint DL/SC rule listings |
optimization_guide.md | Layer optimization and image size reduction techniques |
security_checklist.md | Container security best practices; full CKV_DOCKER_* check listings |
External:
Official Docker Documentation:
Security Guidelines:
Best Practices Resources: