Runs entirely in your browser — nothing leaves this page.
Dockerfile analyzer
Lint a Dockerfile for root containers, unpinned images, leaked secrets, cache busting and image bloat.
or paste it below
What the analyzer checks
The Dockerfile is parsed — continuations joined, comments handled — and 22 rules run over it, covering the things that reliably cause trouble: containers running as root, secrets baked into ENV or ARG, unpinned base images, package-manager caches left in layers, and a COPY ordering that throws away the build cache on every source change.
Everything happens in your browser, which matters because Dockerfiles carry internal registry hosts and, more often than anyone admits, real credentials.
I have a USER instruction — why does it still say the image runs as root?
Only the final stage decides what the container runs as. A USER in a build stage is discarded with that stage. Put the USER in the last stage, after the last operation that needs write access.
Why is ADD flagged when COPY is not?
ADD also unpacks archives and downloads URLs. Both are useful occasionally and surprising the rest of the time — an ADD of a .tar.gz silently extracts it. The rule accepts ADD for remote URLs and archives, and asks for COPY everywhere else.
It flags a secret in my ENV, but the value is a placeholder. Why?
Empty values, ${VAR} references and obvious placeholders are not flagged. A literal value next to a key named like a credential is, because anything set with ENV or ARG stays in the image history and is readable by everyone who pulls it.
Is a single-stage build wrong?
No, it is flagged as information. But if the image compiles anything, the compiler, headers and sources all ship to production. A second stage that copies only the artefact usually removes hundreds of megabytes and most of the attack surface.
Related tools: K8s manifest validator, SBOM viewer and Kubernetes CVEs.