Hadolint
Lints Dockerfiles against best-practice rules and runs ShellCheck on the shell script in every RUN instruction.
github.com/hadolint/hadolint ↗- Stars
- ★ 12,466
- License
- GPL-3.0
- Language
- Haskell
- Latest release
- v2.15.1 · 31 Jul 2026
- Last push
- 25 Sept 2026
- OpenSSF Scorecard
- 4.3 / 10
The standard Dockerfile linter and actively released again, but most rules are about reproducibility and hygiene, so pair it with an image scanner.
How it works
Hadolint is written in Haskell. It parses the Dockerfile into an AST with the language-docker library and runs its DL rules over the instruction list. Because rules see the whole file, some track state, such as which USER is set last.
The shell code in each RUN instruction is handed to ShellCheck, which hadolint embeds, and those findings come back as SC rules next to the DL ones. Hadolint never builds the image, pulls the base image or looks at what is installed in it.
Settings come from .hadolint.yaml (ignored rules, severity overrides, failure-threshold, trustedRegistries for DL3026, a label schema) or from CLI flags. A # hadolint ignore=DL3008,SC2086 comment covers the next instruction and # hadolint global ignore=... covers the file. Output is tty, json, checkstyle, codeclimate, gitlab_codeclimate, gnu, codacy, sonarqube, sarif or junit, and the exit code is non-zero when a finding reaches the failure threshold.
What it catches
- FROM images with no tag or with :latest (DL3006, DL3007)
- Unpinned package versions in apt-get, apk, pip, npm, gem and go install
- Last USER is root, or sudo used in RUN (DL3002, DL3004)
- ADD used where COPY would do (DL3020)
- Base images from registries outside your trusted list (DL3026)
- Credential-looking names in ARG or ENV (DL3064)
- Shell bugs in RUN lines and pipes without pipefail (ShellCheck, DL4006)
Run it
brew install hadolint
hadolint Dockerfile
# or without installing:
docker run --rm -i hadolint/hadolint < DockerfileIn GitHub Actions
hadolint:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@<sha> # v7.0.1
with:
persist-credentials: false
- uses: hadolint/hadolint-action@<sha> # v3.5.0
with:
dockerfile: Dockerfile
format: sarif
output-file: hadolint.sarif
no-fail: true
- uses: github/codeql-action/upload-sarif@<sha> # v4.38.3
with:
sarif_file: hadolint.sarifWhat leaves your machine
Nothing. It reads the Dockerfile locally and does not contact registries.
Limits
- Only sees the Dockerfile text. It cannot tell you about CVEs or secrets baked into the base image or the built layers.
- DL3006 and DL3007 accept any explicit tag, and no rule requires pinning FROM to a sha256 digest.
- Release gaps have been long (v2.12.0 in 2022, then v2.13 in 2025), so check the rule list against the version you actually run.
Links
Related tools
GitHub stats as of 10 Oct 2026. How ratings work.