Dockerfile Linter
Lint Dockerfiles against ~25 hadolint-style rules. Catches the highest-value mistakes — floating tags, missing USER, apt cache leaks, shell-form CMDs.
Errors
1
Warnings
12
Info
3
- warningDL3007line 1
Avoid :latest tag — pin a specific version
Hint: Use a digest or specific tag for reproducible builds
- warningDL4000line 2
MAINTAINER is deprecated — use LABEL maintainer="..."
- warningDL3000line 4
Use absolute WORKDIR path
- warningDL3020line 5
Use COPY instead of ADD for files and folders
Hint: ADD has implicit features (URL fetch, archive extract) that surprise readers
- warningDL3015line 7
apt-get install: add --no-install-recommends to keep image small
- warningDL3009line 7
Clean up apt-get caches in the same RUN: rm -rf /var/lib/apt/lists/*
- infoDL3008line 7
Pin versions in apt-get install (pkg=version)
- warningDL3014line 7
Add -y to apt-get install to avoid interactive prompts
- warningDL3015line 9
apt-get install: add --no-install-recommends to keep image small
- warningDL3009line 9
Clean up apt-get caches in the same RUN: rm -rf /var/lib/apt/lists/*
- infoDL3008line 9
Pin versions in apt-get install (pkg=version)
- errorDL3004line 9
Do not use sudo — it leads to unpredictable behavior
- warningDL3011line 11
EXPOSE port "99999" is out of range (1..65535)
- warningDL3025line 13
CMD should use the JSON exec form ["cmd", "arg"] not shell form
- warningDL3002line 1
No USER set — image runs as root
Hint: Add a USER instruction with a non-root user before CMD/ENTRYPOINT
- infoDL3009line 9
Multiple RUN apt-get lines — combine into one to reduce layers (2 found)
About Dockerfile Linter
Lint Dockerfiles against ~25 hadolint-style rules covering the highest-value problems: floating tags, missing USER, ADD vs COPY, apt-get cache leaks, pip/npm version pinning, shell-form CMD/ENTRYPOINT, sudo usage, non-absolute WORKDIR, deprecated MAINTAINER, and out-of-range EXPOSE ports. All analysis runs in your browser.
Rule categories
Security
Missing USER (runs as root), sudo usage, :latest tags, ADD with URLs.
Image size
apt-get cache not cleaned, --no-install-recommends missing, pip --no-cache-dir missing, multiple apt-get RUN layers.
Correctness
Shell-form CMD/ENTRYPOINT, non-absolute WORKDIR, cd in RUN, out-of-range EXPOSE.
Maintenance
Deprecated MAINTAINER, unpinned apt/pip/npm versions.
Pipeline
- Docker Compose Visualizer — visualize the service stack that uses this Dockerfile.
- Kubernetes Validator — validate the K8s manifests that deploy this image.
Frequently asked
- Why should I avoid the :latest tag?
- The :latest tag is mutable — it points to a different image every time the upstream maintainer pushes a new build. Using :latest means your image can change between builds without any change to your Dockerfile, breaking reproducibility. Pin to a specific version tag (e.g. nginx:1.27.0) or a digest (e.g. nginx@sha256:...) for reproducible builds.
- Why should I add a USER instruction?
- By default, Docker containers run as root. If an attacker exploits a vulnerability in your application, they have root access inside the container. Adding a non-root USER reduces the blast radius. Create a dedicated user in your Dockerfile: RUN addgroup -S app && adduser -S app -G app, then USER app.
- Why use COPY instead of ADD?
- ADD has two implicit behaviours that surprise readers: it can fetch URLs (downloading arbitrary content at build time) and it automatically extracts tar archives. COPY does exactly one thing: copy files from the build context. Use COPY for files and directories; use ADD only when you specifically need the archive extraction feature.
- Why should I clean apt-get caches in the same RUN?
- Docker layers are immutable. If you run apt-get install in one RUN and rm -rf /var/lib/apt/lists/* in a separate RUN, the cache files are still present in the first layer and contribute to the final image size. Combining them in a single RUN ensures the cache is never committed to any layer.
- What is the exec form vs shell form for CMD and ENTRYPOINT?
- Shell form (CMD echo hello) runs the command via /bin/sh -c, which means signals like SIGTERM are sent to the shell, not your process. This causes graceful shutdown to fail. Exec form (CMD ["echo", "hello"]) runs the command directly as PID 1, so signals are delivered correctly. Always use exec form for CMD and ENTRYPOINT.