Dockerfile Validator

Paste a Dockerfile to catch typos in instructions before docker build fails halfway through a long build. Valid files are formatted in the same step.

Input

Settings

History

Load from URL

What gets checked

Docker reads a Dockerfile line by line, and each logical line must start with a known instruction. The validator walks the file the same way, following \ line continuations and heredoc bodies (RUN <<EOF ... EOF), and checks two rules:

  1. Every instruction must exist. FROM, RUN, CMD, LABEL, EXPOSE, ENV, ADD, COPY, ENTRYPOINT, VOLUME, USER, WORKDIR, ARG, ONBUILD, STOPSIGNAL, HEALTHCHECK, SHELL and the deprecated MAINTAINER are accepted in any letter case. A typo such as COPPY or FORM is an error, reported with its line, and the file is not formatted until it is fixed.
  2. Only ARG may come before the first FROM. A RUN or COPY above it is reported as a warning, because Docker rejects it but the rest of the file is still readable.

Comments, blank lines and parser directives such as # syntax=docker/dockerfile:1 are skipped.

The most common real-world trigger for an unknown-instruction error is not a typo at all but a lost backslash. When one line of a long RUN apt-get install ... \ chain loses its trailing \, the next line (curl \, say) becomes its own instruction, and the message names that command. If the reported word looks like a shell command, check the end of the line above it.

Two known limitations: the checker assumes the default backslash continuation character, so Windows images that switch to a backtick with the escape parser directive get false errors on their continuation lines; and a # comment placed between the lines of a continued RUN ends the continuation as far as the checker is concerned, although Docker accepts it. Move such comments above the instruction.

From validation to formatting

Once no errors remain, the file is passed to dprint’s Dockerfile plugin, compiled to WebAssembly, which normalises spacing and instruction layout while keeping your continuation lines. If you introduce an error later, the instruction name is shown in the message (Unknown instruction 'COPPY'), its line is highlighted, and the output pane holds on to the last formatted version in a dimmed style. Use Ctrl/Cmd+Enter to format and Ctrl/Cmd+Shift+C to copy.

Nothing is sent to a registry or a daemon; the check happens in your browser, so build arguments that reference private registries stay private.

What docker build checks that this page does not

The validator does not run BuildKit, so anything that depends on the build context or the network is out of scope: whether a base image tag exists, whether a COPY source path is present, whether npm ci will succeed. Instruction arguments are not parsed in detail either. An exec-form CMD with an unbalanced JSON array, for example CMD ["gunicorn", "app:app", passes here; Docker would then silently run it in shell form. Flags such as --mount or --chmod are not checked against your Docker version.

For best-practice linting (pin image versions, combine apt-get update with install, avoid latest), use hadolint or docker build --check. They complement this syntax check rather than replace it.

Examples

Misspelled COPY instruction

Invalid: COPPY on line 3 is not a Dockerfile instruction, so validation stops there.

Input
FROM node:22-alpine
WORKDIR /app
COPPY package*.json ./
RUN npm ci
COPY . .
CMD ["node", "server.js"]
Result
Line 3, column 1: Unknown instruction 'COPPY'
Open this example in the tool

FROM typed as FORM

Invalid: the very first instruction is misspelled, which docker build would also reject before doing anything.

Input
FORM python:3.12-slim
WORKDIR /srv
RUN pip install --no-cache-dir flask gunicorn
Result
Line 1, column 1: Unknown instruction 'FORM'
Line 2, column 1: WORKDIR before the first FROM
Open this example in the tool

ARG before FROM in a multi-stage build

Passes: ARG is the one instruction allowed before FROM, and both stages are checked.

Input
ARG NODE_VERSION=22
FROM node:${NODE_VERSION}-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci && npm run build

FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html
Output
ARG NODE_VERSION=22
FROM node:${NODE_VERSION}-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci && npm run build

FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html
Open this example in the tool

Heredoc in a RUN instruction

Passes: the lines inside the heredoc are treated as script, not as Dockerfile instructions.

Input
# syntax=docker/dockerfile:1
FROM debian:12-slim
RUN <<EOF
apt-get update
apt-get install -y --no-install-recommends curl
rm -rf /var/lib/apt/lists/*
EOF
Output
# syntax=docker/dockerfile:1
FROM debian:12-slim
RUN <<EOF
apt-get update
apt-get install -y --no-install-recommends curl
rm -rf /var/lib/apt/lists/*
EOF
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
Unknown instruction 'COPPY'The first word of a line is not a Dockerfile instruction, usually a typo or a shell command missing its RUN.Correct the instruction name, or prefix shell commands with RUN.
RUN before the first FROMA build step appears above the base image; only ARG is allowed there.Move the line below FROM, or turn it into an ARG if it defines a build argument.
Unknown instruction 'npm'A line continuation backslash is missing at the end of the previous RUN line, so the next line is read as a new instruction.End the previous line with \ so the command continues.

Frequently asked questions

Are lowercase instructions valid?

Yes. Docker treats instructions case-insensitively, and so does the validator. Uppercase is the convention; the formatter uppercases some instructions, such as FROM, RUN and COPY, but leaves others as written.

Does it pull images or check that tags exist?

No. Nothing is fetched. Base image names and tags are only checked by docker build or your registry.

Can it validate Containerfiles for Podman?

Yes. Containerfile uses the same syntax as a Dockerfile, including multi-stage builds and heredocs.

What is the difference between this and hadolint?

This page catches structural mistakes that stop a build. hadolint adds best-practice rules and runs ShellCheck on RUN commands, so use both.

Related tools