Dockerfile linter
Check a Dockerfile for common mistakes and best-practice issues, with an explanation for each finding.
Try:
All rules (51)
| Rule | Severity | Checks for | Why it matters |
|---|---|---|---|
| XT1001 | Error | Unknown instruction | The builder stops with a parse error when it meets an instruction it does not know. |
| XT1002 | Error | FROM must come first | Only parser directives, comments and global ARG instructions may appear before the first FROM. |
| XT1003 | Error | Invalid escape directive | The escape directive only accepts a backslash or a backtick. |
| XT1004 | Error | Missing arguments | Every instruction needs at least one argument, so the build fails here. |
| XT1005 | Warning | Whitespace after line continuation | Invisible spaces after the escape character are easy to miss and some tools stop treating the line as continued. |
| XT1006 | Error | Unterminated heredoc | Without its closing delimiter the heredoc swallows the rest of the file. |
| XT1007 | Warning | Empty continuation line | Blank lines inside a continued instruction are deprecated and may become an error. |
| XT1008 | Warning | File ends with a line continuation | The last instruction expects another line that never comes, which usually means something was cut off. |
| XT1009 | Info | Inconsistent instruction casing | Instructions are case-insensitive, but mixing cases makes the file harder to read; uppercase is the convention. |
| XT1101 | Warning | Base image without a tag | Without a tag the builder pulls "latest", so the same Dockerfile can produce different images over time. |
| XT1102 | Warning | Base image uses the latest tag | The "latest" tag moves whenever a new version is pushed, which makes builds unpredictable. |
| XT1103 | Error | Duplicate stage name | Stage names must be unique so that FROM and COPY --from can refer to them unambiguously. |
| XT1104 | Error | COPY --from refers to an unknown stage | A stage can only copy from stages defined above it; anything else is pulled as an image, which is rarely intended. |
| XT1105 | Error | Malformed FROM | FROM takes an image, optionally followed by AS and a stage name that starts with a letter. |
| XT1106 | Info | Hard-coded platform | A fixed --platform prevents multi-platform builds; $BUILDPLATFORM or $TARGETPLATFORM keep them working. |
| XT1107 | Info | AS casing differs from FROM | Matching the casing of FROM and AS keeps the file consistent. |
| XT1108 | Warning | Undefined variable in FROM | Variables in FROM only come from ARG instructions placed before the first FROM, or from built-in platform arguments. |
| XT1109 | Warning | COPY --from names an image | A --from value that is not a stage is pulled as an image; that works, but a typo in a stage name looks the same. |
| XT1201 | Warning | MAINTAINER is deprecated | MAINTAINER was replaced by a label such as org.opencontainers.image.authors. |
| XT1202 | Warning | Legacy "key value" form | The space-separated form only allows one variable and is deprecated; "key=value" is clearer. |
| XT1301 | Warning | Final stage runs as root | Without a USER instruction the container runs as root, which makes a container escape far more damaging. |
| XT1302 | Warning | Last USER is root | Switching back to root at the end means the container runs with full privileges. |
| XT1303 | Warning | sudo in RUN | Build steps already run as the current USER; sudo adds an unneeded binary and confusing privilege changes. |
| XT1401 | Warning | apt-get install without -y | Without -y apt-get waits for a confirmation that never comes in a build and aborts. |
| XT1402 | Warning | apt-get install without --no-install-recommends | Recommended packages are rarely needed in an image and can add a lot of size and attack surface. |
| XT1403 | Warning | apt lists not cleaned | The package lists in /var/lib/apt/lists stay in the layer unless they are removed in the same RUN. |
| XT1404 | Warning | Upgrading all packages | Upgrading everything in a build makes images unpredictable; use a newer base image or pin the packages you need. |
| XT1405 | Warning | apt instead of apt-get | apt is meant for interactive use and its command-line interface is not stable for scripts. |
| XT1406 | Warning | apk add without --no-cache | Without --no-cache the package index stays in the layer and bloats the image. |
| XT1407 | Warning | yum/dnf cache not cleaned | Package manager caches stay in the layer unless they are cleaned in the same RUN. |
| XT1408 | Warning | Package install without a yes flag | Without a non-interactive flag the package manager waits for a confirmation and the build fails. |
| XT1409 | Warning | pip install without --no-cache-dir | pip keeps downloaded packages in its cache, which ends up in the image's layer. |
| XT1410 | Info | npm install instead of npm ci | npm ci installs exactly what the lockfile says, so builds are reproducible. |
| XT1411 | Warning | apt-get update on its own | A cached update layer goes stale, so a later install can fail or fetch outdated packages; update and install in the same RUN. |
| XT1501 | Warning | Piping a download into a shell | Running a script straight from the network executes whatever the server sends, without any verification. |
| XT1502 | Warning | cd in RUN | WORKDIR sets the directory for every following instruction and is easier to follow than cd inside commands. |
| XT1503 | Info | Consecutive RUN instructions | Each RUN creates a layer; related commands joined with && produce fewer, smaller layers. |
| XT1504 | Info | Pipe without pipefail | In a pipeline only the last command decides success, so a failing download can go unnoticed. |
| XT1601 | Warning | Relative WORKDIR | A relative WORKDIR depends on every earlier WORKDIR, which is easy to break; absolute paths are clearer. |
| XT1701 | Warning | ADD for local files | COPY is more predictable for local files; ADD also extracts archives and downloads URLs. |
| XT1702 | Warning | ADD from a URL | ADD downloads without verifying the file; add --checksum, or download and verify it in a RUN step. |
| XT1703 | Error | Several sources need a directory destination | When COPY or ADD has more than one source, the destination must be a directory ending with a slash. |
| XT1801 | Warning | Shell form for CMD or ENTRYPOINT | In shell form the process runs under /bin/sh -c, which does not forward signals, so the container cannot stop gracefully. |
| XT1802 | Warning | Instruction overridden later in the stage | Only the last CMD, ENTRYPOINT or HEALTHCHECK of a stage takes effect. |
| XT1803 | Error | Invalid exec form | When the JSON array cannot be parsed the builder silently falls back to shell form and runs the brackets as a command. |
| XT1901 | Error | Invalid EXPOSE | EXPOSE takes container ports (1–65535 or a range) with an optional /tcp, /udp or /sctp protocol. |
| XT2001 | Warning | Secret in ENV or ARG | ENV and ARG values are stored in the image metadata and history, where anyone with the image can read them. |
| XT2002 | Info | Secret passed as a build argument | Build arguments show up in the image history; a secret mount (RUN --mount=type=secret) keeps them out of it. |
| XT2101 | Info | No HEALTHCHECK | Without a HEALTHCHECK, Docker cannot tell a running container from a working one. |
| XT2103 | Error | Malformed HEALTHCHECK | HEALTHCHECK takes either NONE or CMD followed by a command. |
| XT2204 | Error | Invalid ONBUILD trigger | ONBUILD cannot wrap FROM, MAINTAINER or another ONBUILD. |
The rule set and its wording are this tool’s own. The Dockerfile is checked in your browser and never leaves it.