Docker "dockerfile parse error" - Fix Dockerfile Syntax in CI
BuildKit could not parse the Dockerfile itself - before running any step. The error names a line and column; the fix is almost always right there.
What this error means
The build fails instantly with dockerfile parse error on line N or unknown instruction. No RUN/COPY steps execute because the file never parsed.
ERROR: failed to solve: dockerfile parse error on line 12: unknown instruction: RUNN
# or: unexpected end of statement while looking for matching ...Diagnose it: build context, cache, or platform?
A Dockerfile that builds locally and fails in CI usually differs in one of three ways: the build context contains different files, the layer cache is cold or poisoned, or the runner architecture does not match what the base image provides.
# what is actually being sent as build context (dockerignore applies)
docker build --no-cache --progress=plain -t probe . 2>&1 | head -40
# what platform are you on, and what does the base image support?
docker version --format '{{.Server.Arch}}'
docker buildx imagetools inspect <base-image> | grep -i platform
# prove it is not a cache artefact
docker build --no-cache .Common causes
Misspelled or unknown instruction
A typo like RUNN, FORM, or COPPY, or a directive that is not a real Dockerfile instruction, makes the parser reject the line.
Broken line continuation
A trailing backslash followed by a space, a missing backslash on a multi-line RUN, or Windows CRLF line endings can corrupt the continuation and confuse the parser.
Misplaced parser directive or heredoc
# syntax= or other parser directives must appear at the very top. A heredoc (RUN <<EOF) without a matching terminator also fails to parse.
How to fix it
Go to the reported line and fix the syntax
- Open the Dockerfile at the line/column in the error.
- Correct the instruction spelling and ensure each line continuation ends with a single backslash and no trailing whitespace.
- Move any
# syntax=directive to the very first line.
Normalize line endings and validate
Convert CRLF to LF and re-run with plain output to see the exact failing line.
sed -i 's/\r$//' Dockerfile
docker build --progress=plain .Keep the build context small and deterministic
- A missing
.dockerignoresendsnode_modules,.git, and build output to the daemon, which is slow and can change layer hashes between environments. - A
COPYof a path that exists locally but is gitignored will fail in CI, because the runner only has what the checkout produced. - Multi-arch builds need
buildxand QEMU set up explicitly; a plaindocker buildon an ARM runner silently produces an ARM image.
How to prevent it
- Lint Dockerfiles in CI (e.g. hadolint) before building.
- Enforce LF line endings via .gitattributes for Dockerfiles.
- Keep multi-line RUN blocks tidy with one backslash per continued line.