Skip to content
Free Tool Arena

Developer Utilities · Free tool

Dockerfile Lint Helper

Scan a Dockerfile for common smells — latest tag, no USER, ADD for URLs, secrets in RUN, missing HEALTHCHECK, and more.

Updated June 2026
7 issues found
  • infoNo HEALTHCHECK instruction — container orchestrators can't verify readiness.
  • errorNo non-root USER declared — container will run as root.
  • warnL1Avoid 'latest' tag — pin an explicit version for reproducible builds.
  • warnL3COPY . before dependency install breaks cache — copy package files first, install, then copy rest.
  • warnL4apt-get update in separate RUN — combine with install to avoid cached stale indexes.
  • warnL43 separate RUN layers — consider combining with && to reduce image layers.
  • warnL5apt-get install should use --no-install-recommends to reduce image size.
Found this useful?EmailBuy Me a Coffee

Advertisement

What it does

Paste your Dockerfile and get back an annotated list of common antipatterns and security smells with line numbers. Catches the kinds of issues that cause production incidents: running as root (no USER directive — container processes default to UID 0, dangerous on shared infrastructure), uncacheable layer ordering(COPY . /app before RUN npm install — every code change invalidates the install layer), missing HEALTHCHECK, using :latest tags (non- reproducible builds), unnecessary packages left in the image (apt cache, build dependencies), oversized base images (using ubuntu when alpine or distroless would do).

The check is heuristic, not formal. For deeper analysis use hadolint (the de facto Dockerfile linter, written in Haskell — much more comprehensive), Trivy for vulnerability scanning of the resulting image, or Docker’s built-in docker scout for supply-chain analysis. This tool is a fast first-pass check during writing, before you commit and let CI do the real validation.

Common categories the linter checks: image hygiene (base image, multi-stage builds), security (USER, HTTPS- only downloads, secret leaks in build args), build performance (layer ordering, .dockerignore hints, --no-cache where appropriate), runtime correctness (HEALTHCHECK, EXPOSE matching app port, ENTRYPOINT vs CMD usage), and image size (cleanup of package caches, multi-stage final-image trimming).

Embed this tool on your siteShow snippet

Paste this snippet into any page. Loads on-demand (lazy), no tracking scripts, and sized to most dashboards. Replace the height to fit your layout.

<iframe src="https://freetoolarena.com/embed/dockerfile-lint-helper" width="100%" height="720" frameborder="0" loading="lazy" title="Dockerfile Lint Helper" style="border:1px solid #e2e8f0;border-radius:12px;max-width:720px;"></iframe>
Embed docs →

How to use it

  1. Paste your Dockerfile content into the input box.
  2. Read the issues list — each entry has a line number, severity (warning vs error), and the specific problem with a suggested fix.
  3. Apply fixes in your local Dockerfile, paste again, re-check until clean.
  4. For deeper analysis (especially shellcheck-style checks on RUN commands), pipe through hadolint locally: `docker run --rm -i hadolint/hadolint < Dockerfile`.
  5. Run Trivy or docker scout against the BUILT image to catch package-level CVEs that a Dockerfile linter can't see.

When to use this tool

  • Quick sanity check during Dockerfile authoring before committing.
  • Reviewing teammate Dockerfiles in PR — catch issues before they ship.
  • Onboarding to Docker — the rule explanations teach common best practices.
  • Auditing existing Dockerfiles for security or efficiency improvements.

When not to use it

  • Production CI gating — for that use hadolint with a config file checked into the repo, plus Trivy for image-level scans.
  • Vulnerability scanning of installed packages — that's image scanning, not Dockerfile linting. Use Trivy, Grype, or docker scout.
  • Compliance auditing (CIS Docker Benchmark, NIST) — those have specific frameworks; a heuristic linter is a starting point, not the answer.

Common use cases

  • Pre-decision sanity-check on inputs and outputs
  • Educational use &mdash; demonstrating the underlying concept
  • Onboarding a colleague who needs the same calculation/conversion
  • Verifying a number or output before passing it on

Frequently asked questions

Why does running as root matter?
If a container process is compromised (e.g. via a remote-code-execution vulnerability in your app), an attacker has root inside the container. With certain misconfigurations (Docker socket mounted, --privileged flag, or container-escape vulnerabilities), root inside the container becomes root on the host. Running as a non-root user (USER directive in Dockerfile) limits the blast radius. Most modern base images create a non-root user by default; use it.
What's wrong with `:latest` tags?
`:latest` is a moving target. Today your build pulls v1.2.3; tomorrow the maintainer publishes v1.3.0 as `:latest` and your build is now using a different version. Reproducibility is dead. Pin to specific versions (`node:20.10.0-alpine`) or even better to immutable digests (`node:20.10.0-alpine@sha256:abc123...`). Both pinning approaches give you Sun-Tzu-style strategic certainty about what you're shipping.
Why does layer order matter?
Docker caches each layer. When a layer's command or its inputs change, that layer and everything after it gets rebuilt. So `COPY . /app` followed by `RUN npm install` means: ANY change to your code invalidates the install layer, and `npm install` runs on every build. The fix: copy ONLY package.json/package-lock.json first, run install, then copy the rest. Now code changes don't invalidate the install layer.
What's a HEALTHCHECK and why do I need one?
A periodic command Docker runs inside the container to verify the app is actually working — not just that the process is alive but that it responds correctly (often via HTTP GET on /health). Without it, an app that's hung or crashed but hasn't exited shows as 'running' to Docker — orchestrators don't restart it. With HEALTHCHECK, Kubernetes / Swarm can detect and restart unhealthy containers.
How does this compare to hadolint?
hadolint is the de facto standard — written in Haskell, comprehensive ruleset, used in CI by thousands of projects. This tool is a fast in-browser first-pass with the most common rules. Use this during writing; use hadolint in CI for thoroughness.
What's the smallest base image?
For most languages: distroless (Google's minimal base — only the runtime, no shell). Alpine is small (~5MB) but uses musl libc which sometimes causes subtle bugs. scratch (literally empty) works for static binaries. The right choice depends on language: Go binaries → scratch or distroless; Node.js → distroless-node or alpine; Python → distroless-python or python:3.11-slim.

Advertisement

Learn more

Explore more developer utilities tools

100% in-browserNo downloadsNo sign-upMalware-freeHow we keep this safe →

Found this useful?

The tools stay free thanks to readers who chip in or spread the word.

Buy Me a Coffee