Dockerfile Linter
Check Dockerfiles for common security and portability issues.
Overview
Paste a Dockerfile and the linter flags the usual security and portability mistakes - latest image tags, missing USER directive, apt-get install without --no-install-recommends and cleanup, unpinned package versions, and combinations that bust layer caching. Findings come with a brief note explaining why the rule exists.
It's for developers and platform engineers who want a quick sanity check before opening a PR. Reach for it when reviewing infrastructure changes, evaluating a base image candidate, or auditing third-party Dockerfiles you're considering vendoring into your own build.
How it works
The linter parses the Dockerfile against the syntax documented in the official Dockerfile reference, then runs a series of rule checks against each instruction. Rules cover the OWASP container security recommendations (run as non-root, minimal base images, no embedded secrets), the Docker BuildKit best-practices guide (multi-stage builds, cache-friendly ordering), and ecosystem-specific gotchas (apt cleanup, npm cache, Python wheel cleanup).
Each rule has a short identifier and severity (info, warning, error) so you can decide which to enforce in CI. The rule set focuses on portable correctness rather than stylistic preferences.
Examples
- Using
latesttag:FROM node:latest # warning: tag this to a specific version - Running as root:
FROM ubuntu:22.04 CMD ["myapp"] # warning: no USER directive; container runs as root - Inefficient apt-get:
RUN apt-get update && apt-get install -y curl # warning: missing --no-install-recommends and rm -rf /var/lib/apt/lists/* - Hardcoded secret:
ENV AWS_SECRET_KEY=abc123 # error: secret in env layer; use BuildKit secrets
FAQ
How does it compare to hadolint?
The rule coverage overlaps with the most-used hadolint rules but is intentionally smaller and focused on actionable findings. For exhaustive linting on a CI matrix, hadolint remains the gold standard.
Does it understand multi-stage builds?
Yes - FROM ... AS stage and stage-named COPY --from=stage are parsed correctly. Findings reference the originating stage.
Will it catch shell injection?
It flags obvious patterns (unquoted $VAR in RUN) but isn't a full shell parser. Treat the output as a screening pass, not a security audit.
Why does it warn about ADD?
ADD has surprise behaviours (remote URL fetching, automatic tar extraction). COPY is recommended for local files unless you specifically need ADD's features.