Check a Dockerfile against 55 hadolint rules: pinned versions, root user, cache and more
Runs in your browser. Nothing you type is sent anywhere. Checked against sources on 16 Oct 2026.A Dockerfile linter reads the file without building it and flags risky or wasteful lines. This one applies 55 of hadolint's DL rules, such as DL3008 for unpinned apt-get packages and DL3002 for running as root, and gives each finding its line, level and fix. It runs in your browser, with no install and no Docker.
Paste the Dockerfile into the box, open the file, or click Try an example.
Read the findings, sorted by line: each has a level, its hadolint code, what is wrong and how to fix it.
Click a finding to jump to its line, fix it, and watch the list update as you type.
Click Copy report to take the findings as text, for a pull request or a ticket.
A Dockerfile can build today and break next month: an unpinned base image moves, an apt-get install picks up a new version, a cache left in a layer makes the image hundreds of megabytes larger. A linter catches these before they ship. hadolint is the standard one in CI pipelines; this page applies its Dockerfile rules in your browser.
What it checks. Every finding names its line, its hadolint code, a level and a one-line fix. The rules fall into five groups:
| Group | Examples |
|---|---|
| Reproducible builds | DL3006 untagged image, DL3007 latest, DL3008 apt-get, DL3013 pip, DL3016 npm, DL3018 apk |
| Smaller images | DL3009 apt lists, DL3015 recommends, DL3019 apk cache, DL3042 pip cache, DL3059 extra RUN layers |
| Security | DL3002 root user, DL3004 sudo, DL4006 pipefail |
| Correctness | DL3011 port range, DL3021 COPY target, DL3022 and DL3023 stage names, DL3044 ENV, DL3061 order |
| Clear intent | DL3000 WORKDIR, DL3003 cd, DL3020 ADD, DL3025 JSON CMD, DL4000 MAINTAINER |
How close it is to hadolint. The rules were written from hadolint 2.12's source, and the tests run the real hadolint binary's answers for more than 80 Dockerfiles: the same codes on the same lines, every time. Multi-stage builds, ONBUILD, continuation lines, the escape directive and inline # hadolint ignore= comments all behave as in hadolint. ShellCheck's SC warnings about the shell code inside RUN lines are not included.
Silencing a rule. Put # hadolint ignore=DL3008 on the line before an instruction to skip that rule there, or # hadolint global ignore=DL3059 anywhere to skip it for the whole file. The summary says how many findings were switched off.
Everything runs in your browser: the Dockerfile you paste or open is never uploaded.
DL3008 says an apt-get install line names packages without versions, so each build may install something different. Write package=version, such as curl=7.88.1-10+deb12u5, and find the current version with apt-cache policy curl inside the base image. Pinning makes the image reproducible; update the pins on purpose, not by accident.
A container that runs as root has root rights inside it, so an attacker who breaks into the application can do more, and a mistake in a mounted volume can change host files. Create a user in a RUN, such as useradd app, and finish the stage with USER app. Build steps before that can still run as root.
Every RUN makes a layer, and a file removed in a later layer still takes space in the earlier one. apt-get update downloads package lists of tens of megabytes, so remove them in the same RUN with && rm -rf /var/lib/apt/lists/*. Removing them in a separate RUN saves nothing.
Write a comment directly above the instruction: # hadolint ignore=DL3008, or several codes separated by commas. To switch a rule off for the whole file, write # hadolint global ignore=DL3059 anywhere. Both work in hadolint itself and on this page, and the summary counts what was switched off.
For the Dockerfile rules, yes: the 55 DL codes, their levels and their conditions follow hadolint 2.12, and the tests compare against the real hadolint binary on more than 80 files. Not included are ShellCheck's SC warnings about the shell code inside RUN lines, and the rules that need a configuration file, such as allowed registries.
Use COPY for files and folders. ADD also downloads URLs and unpacks local tar archives, which is useful when you want exactly that and surprising when you do not. hadolint flags ADD for a plain file as DL3020, and flags a COPY followed by tar -x of the same archive as DL3010, where ADD would do it in one step.
Rates and rules change; check the source before you rely on a figure.
Still stuck? Ask about Dockerfile Linter and anybody who knows can answer. No account needed.
Same job, other tools: Twitter Card Validator – Check twitter:card tags and the og: tags X falls back to.
On the related tools: Readability Checker – Flesch reading ease and grade level, with what to change · JSONPath Evaluator – Evaluate a JSONPath expression and get the matching values and their paths.
Open it set for: Dockerfile Validator.