This error occurs when Docker cannot find a file specified in the ADD or COPY instruction. The file either does not exist in the build context directory, is located outside the build context, or has been excluded by a .dockerignore rule.
The "ADD failed: file not found in build context or excluded by .dockerignore" error indicates that Docker's build process cannot locate a file you're trying to copy into your image. This happens during the image build phase when Docker processes ADD or COPY instructions in your Dockerfile. The build context is the directory (and its subdirectories) that you specify when running `docker build`. Docker sends this entire context to the Docker daemon before starting the build. The key constraint is that ADD and COPY can only access files within this build context - they cannot reach files outside it, regardless of how you write the path. There are two main causes: either the file genuinely doesn't exist at the specified path relative to the build context, or the file exists but is being filtered out by .dockerignore patterns before Docker even sees it.
First, confirm the file actually exists where you expect it:
# List files in your build context directory
ls -la ./path/to/file
# Or find files matching a pattern
find . -name "filename*" -type fCheck for typos in both the filename and the path. Paths in Docker are case-sensitive, even on Windows/macOS.
Compare the path in your Dockerfile with the actual file location:
# If your Dockerfile says:
COPY src/config.json /app/
# Then this file must exist:
# ./src/config.json (relative to build context)If the file exists but Docker can't see it, check if .dockerignore is excluding it:
# View your .dockerignore
cat .dockerignoreCommon problematic patterns:
# These patterns might accidentally exclude your file:
* # Excludes everything!
*.json # Excludes all JSON files
src/ # Excludes entire src directory
**/*.config # Excludes all .config files in any directoryTo fix, either remove the offending pattern or add a negation rule. Order matters - negations must come after the exclusion:
# Exclude all, then re-include specific files
*
!src/
!src/**
!package.json
!DockerfileTip: Temporarily rename .dockerignore to test if it's the cause:
mv .dockerignore .dockerignore.bak
docker build -t test .
mv .dockerignore.bak .dockerignoreThe build context is determined by where you run the docker build command. Ensure you're in the right directory:
# Check current directory
pwd
# The '.' at the end sets the build context to current directory
docker build -t myimage .If your Dockerfile is in a subdirectory, you have two options:
Option A: Run from parent directory with -f flag:
# From project root
docker build -f docker/Dockerfile -t myimage .Option B: Run from the Dockerfile's directory:
cd docker
docker build -t myimage .
# Note: Now COPY paths must be relative to docker/ directoryFor CI/CD pipelines, explicitly set the working directory before building.
COPY and ADD paths must be relative to the build context, not absolute or relative to Dockerfile location.
Wrong - absolute path:
COPY /home/user/myapp/config.json /app/ # Will look for ./home/user/myapp/config.jsonWrong - parent directory:
COPY ../shared/utils.js /app/ # Cannot access parent of build contextCorrect - relative to build context:
COPY config.json /app/
COPY src/ /app/src/If you need files from outside the build context, you have two options:
1. Expand the build context:
# Run from parent directory that contains both folders
cd ..
docker build -f app/Dockerfile -t myimage .2. Copy files into build context before building:
cp ../shared/utils.js ./lib/
docker build -t myimage .In docker-compose.yml, the context determines the build context directory. Common mistakes:
Problem: Context doesn't include required files:
services:
app:
build:
context: ./app # Only ./app/ is sent to Docker
dockerfile: DockerfileSolution A: Expand context to parent:
services:
app:
build:
context: . # Entire project is the context
dockerfile: app/DockerfileSolution B: Restructure to keep files in context:
services:
app:
build:
context: ./app
dockerfile: Dockerfile
# Ensure all COPY sources exist within ./app/After changing context, update COPY paths in Dockerfile to match:
# If context is now project root instead of ./app:
COPY app/src/ /app/src/ # Was: COPY src/ /app/src/
COPY shared/ /app/shared/ # Now accessibleSymlinks that point to files outside the build context will fail:
# Check if file is a symlink
ls -la config.json
# lrwxrwxrwx config.json -> /etc/myapp/config.json # This won't work!Docker follows symlinks, but the target must be within the build context.
Fix: Replace symlink with actual file:
# Remove symlink and copy actual file
rm config.json
cp /etc/myapp/config.json ./config.jsonOr use a build argument to inject the content:
ARG CONFIG_CONTENT
RUN echo "$CONFIG_CONTENT" > /app/config.jsondocker build --build-arg CONFIG_CONTENT="$(cat /etc/myapp/config.json)" -t myimage .Docker does not support trailing comments on the same line as COPY or ADD instructions. They get interpreted as part of the filename:
Wrong:
COPY config.json /app/ # Important config file
# Docker looks for file named "config.json /app/ # Important config file"Correct:
# Important config file
COPY config.json /app/This is a common gotcha for developers coming from languages where trailing comments are standard.
Understanding build context transfer: When you run docker build, the CLI packages the entire build context into a tarball and sends it to the Docker daemon. This happens before any Dockerfile instructions run. Use docker build output to see context size:
Sending build context to Docker daemon 45.2MBIf this is unexpectedly large or small, it indicates context issues.
BuildKit and .dockerignore: With BuildKit (default in Docker 20.10+), you can use .dockerignore patterns more efficiently. BuildKit only transfers files that are actually referenced in COPY/ADD instructions, making large exclusion lists less critical for performance.
Multi-stage builds and context: In multi-stage builds, COPY --from copies from another stage, not the build context:
FROM golang:1.21 AS builder
COPY . .
RUN go build -o /app
FROM alpine
COPY --from=builder /app /app # From builder stage, not build context
COPY config.json /etc/ # From build contextDebugging context contents: To see exactly what Docker receives, create a Dockerfile that lists the context:
FROM busybox
COPY . /context
RUN find /context -type fRemote build contexts: Docker supports building from Git URLs or tarballs:
docker build https://github.com/user/repo.git#main:dockerWhen using remote contexts, local .dockerignore doesn't apply - use .dockerignore committed to the repo.
Heredoc syntax (BuildKit): For small config files, consider inline content to avoid COPY issues:
# syntax=docker/dockerfile:1
COPY <<EOF /app/config.json
{"key": "value"}
EOFimage operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub