This error occurs when Docker encounters an unrecognized command or malformed syntax in your Dockerfile. Common causes include file encoding issues, missing RUN prefixes, incorrect line continuations, or Windows line endings (CRLF vs LF).
When you run `docker build`, Docker parses your Dockerfile line by line to understand what instructions to execute. Docker recognizes a specific set of valid instructions like FROM, RUN, COPY, CMD, ENTRYPOINT, WORKDIR, etc. as defined in the official Dockerfile reference. The "unknown instruction" error means Docker encountered text that doesn't match any valid Dockerfile instruction. This typically happens when: - You've used a shell command directly without the RUN prefix - Your file has encoding issues (like UTF-16 BOM or CRLF line endings) - You've made a syntax error with line continuations (backslashes) - You have extra line breaks splitting an instruction - There's a typo in an instruction name Docker is strict about Dockerfile syntax for good reason—a single typo or formatting issue can completely change how your container is built, potentially introducing security vulnerabilities or broken deployments.
File encoding issues are a common cause, especially if you're using VS Code or copying from web pages.
Check encoding in VS Code:
1. Open your Dockerfile
2. Look at the bottom-right corner of VS Code
3. It should say "UTF-8"
4. If it says "UTF-16 LE" or has "BOM", click it and select "Save with Encoding" → "UTF-8"
Check encoding from command line:
file DockerfileShould output: Dockerfile: ASCII text or Dockerfile: UTF-8 Unicode text
If you see UTF-16, UTF-16 LE, or with BOM, convert it:
iconv -f UTF-16 -t UTF-8 Dockerfile > Dockerfile.fixed
mv Dockerfile.fixed DockerfileWindows uses CRLF (\r\n) line endings while Linux/Docker expects LF (\n). This is especially common when editing on Windows.
Check line endings in VS Code:
1. Look at the bottom-right corner
2. It should say "LF"
3. If it says "CRLF", click it and select "LF"
Convert line endings from command line (Windows):
dos2unix DockerfileIf you don't have dos2unix:
sed -i 's/\r$//' DockerfileConfigure Git to handle line endings correctly:
# In your repository root
echo "* text=auto" > .gitattributes
echo "Dockerfile text eol=lf" >> .gitattributesDocker instructions must be valid Dockerfile commands. Shell commands need to be prefixed with RUN.
Incorrect:
FROM ubuntu:22.04
apt-get update
apt-get install -y curlCorrect:
FROM ubuntu:22.04
RUN apt-get update
RUN apt-get install -y curlOr combine them:
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curlCommon commands that need RUN:
- apt-get, apt
- yum, dnf
- npm install
- pip install
- curl, wget
- Any shell command
Multi-line commands require a backslash (\) at the end of each line to continue to the next.
Incorrect:
RUN apt-get update
apt-get install -y curl
apt-get cleanCorrect:
RUN apt-get update && \
apt-get install -y curl && \
apt-get cleanImportant rules:
- Backslash must be the LAST character on the line (no spaces after)
- The backslash escapes the newline character
- Proper indentation improves readability but isn't required
For complex multi-line content, use heredoc (requires BuildKit):
RUN <<EOF
apt-get update
apt-get install -y curl
apt-get clean
EOFUnintended line breaks can split an instruction into multiple lines, causing Docker to interpret part of the command as a new instruction.
Check for:
- Blank lines within a command
- Line breaks inside JSON arrays for CMD/ENTRYPOINT
Incorrect:
CMD[
"java",
"-jar",
"app.jar"
]Correct:
CMD ["java", "-jar", "app.jar"]Or with proper continuation:
CMD ["java", \
"-jar", \
"app.jar"]Verify all instruction names are spelled correctly. Docker is case-insensitive for instructions, but typos will cause parse errors.
Valid Dockerfile instructions:
- FROM - Base image
- RUN - Execute command
- CMD - Default command
- COPY / ADD - Copy files
- WORKDIR - Set working directory
- ENV - Set environment variable
- EXPOSE - Expose port
- ENTRYPOINT - Configure container executable
- LABEL - Add metadata
- ARG - Build-time variable
- USER - Set user
- VOLUME - Create mount point
Common typos:
- WRKDIR → WORKDIR
- ENVIROMENT → ENV
- EXPOSE_PORT → EXPOSE
Reference: https://docs.docker.com/engine/reference/builder/
If you have multiple files with "Dockerfile" in the name, Docker might pick up the wrong one.
Check for conflicting files:
find . -iname "*dockerfile*"Common conflicts:
- Dockerfile (primary)
- dockerfile (lowercase - can conflict on case-insensitive filesystems)
- Dockerfile.new, Dockerfile.backup
- Dockerfile in subdirectories
Fix:
- Rename backup/alternate Dockerfiles to not start with "Dockerfile"
- Use specific Dockerfile with -f flag:
docker build -f Dockerfile.prod -t myapp:latest .After making changes, test your Dockerfile:
docker build -t test-build .Enable BuildKit for better error messages:
DOCKER_BUILDKIT=1 docker build -t test-build .BuildKit provides clearer error messages and supports advanced features like heredocs.
Validate syntax without building:
Use a Dockerfile linter like hadolint:
docker run --rm -i hadolint/hadolint < DockerfileThis catches syntax errors and suggests best practices.
### BuildKit and Advanced Syntax
Docker BuildKit (enabled with DOCKER_BUILDKIT=1) supports enhanced syntax features:
Heredoc syntax for multi-line commands:
# syntax=docker/dockerfile:1.4
RUN <<EOF
apt-get update
apt-get install -y curl wget
apt-get clean
rm -rf /var/lib/apt/lists/*
EOFMulti-line COPY with heredoc:
COPY <<EOF /app/config.json
{
"key": "value",
"nested": {
"data": true
}
}
EOFEnable BuildKit by default by adding to ~/.docker/daemon.json:
{
"features": {
"buildkit": true
}
}### IDE and Editor Configuration
VS Code:
Install the "Docker" extension for syntax highlighting and validation.
Configure default line endings:
Add to .vscode/settings.json:
{
"files.eol": "\n",
"[dockerfile]": {
"files.encoding": "utf8"
}
}EditorConfig:
Create .editorconfig in your project root:
[Dockerfile*]
end_of_line = lf
charset = utf-8
insert_final_newline = true### Platform-Specific Notes
Windows:
When working with Docker on Windows (Docker Desktop), always use LF line endings for Dockerfiles, even though Windows natively uses CRLF. Configure Git:
git config --global core.autocrlf inputmacOS:
Encoding issues are less common on macOS, but check if copying from web pages or MS Word.
### Debugging Complex Parse Errors
If you're still getting parse errors after trying the basic fixes:
1. Create a minimal Dockerfile and test:
FROM alpine:latest
RUN echo "test"2. Add instructions back one at a time until you find the problematic line
3. Check hidden characters:
cat -A DockerfileLook for ^M (indicates CRLF) or unusual characters
4. Compare with a working Dockerfile from the same environment
dockerfile parse error line 5: unknown instruction: RRUN
How to fix 'unknown instruction' Dockerfile parse error in Docker
Error response from daemon: manifest for nginx:nonexistent not found: manifest unknown: manifest unknown
How to fix 'manifest for image:tag not found' in Docker
Error response from daemon: invalid reference format: repository name must be lowercase
How to fix 'repository name must be lowercase' in Docker
Error response from daemon: No such image
How to fix 'No such image' in Docker
Error response from daemon: Container is not running
How to fix 'Container is not running' when using docker exec