Dockerfile explainer and linter
Paste a Dockerfile and see what every instruction does, which ones make layers, what a change rebuilds, how the stages connect and roughly how big the image is — with hadolint-style lints and one-click fixes.
Added
How to use it
Paste or type a Dockerfile, or start from a preset: Node, Python, Go (multi-stage), Java, heredocs and secrets, or a deliberately bad one. Everything updates as you type, and nothing leaves the page. Lines with errors or warnings are tinted in the editor.
How to use it
-
Explain — first, what the container will actually run: the final stage’s ENTRYPOINT and CMD combined the way the Dockerfile reference’s table says (shell form becomes
/bin/sh -c …; a shell-form ENTRYPOINT swallows CMD; setting ENTRYPOINT resets an inherited CMD). Type arguments fordocker run IMAGE …to see them replace CMD. Then a card per instruction, by stage: whether it makes a filesystem layer or only changes metadata, what its flags do (--mount=type=cache|secret|ssh|bind,--from,--chown,--link,--platform), what a heredoc runs, which ARGs and ENVs are in scope (an ARG before the first FROM is visible only to FROM lines), and the parser directives (# syntax=,# escape=,# check=). The L-number button jumps to the line in the editor. -
Lint — findings with the rule ids of hadolint (DL3006 untagged base image, DL3007
:latest, DL3008/3013/3016/3018 unpinned packages, DL3009 apt lists left behind, DL3014-y, DL3015--no-install-recommends, DL3020 ADD for local files, DL3025 shell-form CMD, DL3003cd, DL3004sudo, DL4006 pipes withoutpipefail, DL3002 root user, DL3022–3024 stage references, …) and of Docker’s own build checks (SecretsUsedInArgOrEnv,UndefinedVar,FromAsCasing,LegacyKeyValueFormat, …), plus a few from Docker’s best practices (anapt-get updatealone in a RUN, copying the whole context before installing dependencies, no USER). Many have a Fix button that edits the Dockerfile; Apply all applies them one at a time. -
Layers & cache — the final image as a stack: the base image at the bottom, a bar per layer with a rough size, and metadata instructions as dashed lines (they add no layer). Below it, the cache explorer: tick the files you changed (or type paths), the build args you changed, "base image updated", lines you edited, or
--no-cache, and every step says whether it comes from the cache, rebuilds, or depends on whether an earlier stage’s output changed — with the reason. Edit the.dockerignoreto see ignored files stop mattering. When a dependency install re-runs only becauseCOPY . .came first, it says how to reorder. -
Stages — the multi-stage graph: FROM another stage, COPY --from and RUN --mount=from, with the target stage marked and the stages BuildKit skips faded. Choose another
--targetto see what it would build.
The cache rules modelled are Docker’s: a step’s key is its parent plus the instruction; COPY and ADD hash the matched files' contents (not timestamps); RUN compares only its command text; a changed build arg misses at the first RUN after its ARG; COPY --from checksums what it copies; the first miss rebuilds everything after it in that stage (Docker: build cache invalidation).
Limits
-
The size estimate is a ballpark: base images come from a small table of approximate uncompressed linux/amd64 sizes for recent tags (shown under the stack, labelled approximate; Docker Hub shows compressed sizes, about ⅓–½ of these), and package and dependency sizes are typical guesses.
docker historyanddocker imagesgive the real numbers. -
Base images are not fetched: their ENV, USER, ENTRYPOINT and CMD are unknown, so "no USER" and "nothing to run" may be satisfied by the base image.
-
RUN commands are read with a small shell reader, enough to find apt-get, apk, pip, npm, yarn, cd, sudo and pipes — not a full shell parser. hadolint itself also runs ShellCheck, which this doesn’t.
-
The cache model is BuildKit’s in outline;
ADDof URLs and git sources,COPY --linkrebasing and remote cache backends are simplified.
Related: docker run builder (and Compose ↔ docker run), Compose visualiser, Compose and Kubernetes checker, Unix permissions calculator.
Linking to an example
Share link copies a link to the Dockerfile as you have it — a preset by name, otherwise the
text packed into ?s=. Values of ENV and ARG variables that look like secrets (PASSWORD,
TOKEN, SECRET, API keys) are replaced by * first. The tab goes after #:
explain, lint, layers or stages.
| Parameter | Meaning | Example |
|---|---|---|
|
One of the presets below |
|
|
Files changed in the cache explorer, comma-separated |
|
preset= |
Shows |
|---|---|
|
Node.js in three stages: production dependencies, a build stage, and a slim runtime with a healthcheck and |
|
Python slim with apt done right, |
|
Go cross-compiled with |
|
Maven with a dependency cache, then a JRE on Alpine; ENTRYPOINT plus CMD as default arguments |
|
|
|
Most of the classic mistakes at once — try Apply all fixes |
For example ?preset=node&changed=src/server.ts#layers
shows which steps a source change rebuilds.
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.