Fix: Docker COPY Failed: File Not Found in Build Context

The Error

You run docker build and get one of these errors:

COPY failed: file not found in build context
ERROR: failed to solve: failed to read dockerfile: open Dockerfile: no such file or directory

You may also see these variations:

COPY failed: stat /var/lib/docker/tmp/docker-builder123456/some-file.txt: no such file or directory
ADD failed: file not found in build context
failed to compute cache key: failed to calculate checksum of "/some-file.txt": not found

All of these mean the same thing: Docker cannot find a file you referenced in your Dockerfile. The file either doesn’t exist in the build context, is being excluded, or is referenced with the wrong path.

Why This Happens

When you run docker build ., the . at the end is the build context. Docker sends that entire directory to the Docker daemon, and every COPY and ADD instruction can only access files within that context. Nothing outside it exists as far as Docker is concerned.

Here’s what typically goes wrong:

  • The file is outside the build context. You’re referencing a file that lives in a parent directory or somewhere not included in the context path.
  • .dockerignore is excluding the file. Your .dockerignore has a pattern that matches the file you’re trying to copy.
  • The source path in COPY/ADD is wrong. Paths in COPY are relative to the build context root, not relative to the Dockerfile’s location.
  • The Dockerfile itself is not found. You’re running the build from a directory that doesn’t contain a Dockerfile, or the file has a different name or casing.

How the Docker Build Context Works

This is the key concept. When you run:

docker build -t myapp .

The . means “use the current directory as the build context.” Docker packages up everything in that directory and sends it to the daemon. Your COPY and ADD instructions can only reference files from within that package.

project/
├── Dockerfile
├── src/
│   └── app.js
├── package.json
└── config/
    └── nginx.conf

If you run docker build . from inside project/, these work:

COPY package.json .          # ✅ file is in context root
COPY src/ ./src/             # ✅ directory is in context
COPY config/nginx.conf .     # ✅ relative to context root

These don’t:

COPY ../other-project/lib .  # ❌ parent directory is outside context
COPY /home/user/secrets.env . # ❌ absolute path outside context

Docker cannot reach outside the build context. This is a security boundary, not a bug.

Fix 1: Check the Build Context

Make sure you’re running docker build from the right directory with the right context path.

The most common mistake is running the build from the wrong directory:

# You are in /home/user
docker build .

# But your Dockerfile and source code are in /home/user/myapp

Fix: cd into the correct directory or specify the path:

docker build /home/user/myapp

If your project structure requires the build context to be a parent directory, use the -f flag to point to the Dockerfile:

# Use parent directory as context, but specify Dockerfile location
docker build -f services/api/Dockerfile .

Verify what’s in your build context. A quick way to see what Docker sees:

# List everything that would be included in the build context
# (minus .dockerignore exclusions)
ls -la

For a more precise check, you can temporarily add this to your Dockerfile:

FROM busybox
COPY . /context
RUN find /context -type f

Build it and you’ll see every file Docker has access to.

Fix 2: Fix .dockerignore

Your .dockerignore file might be excluding the file you need. This is one of the most common causes and the hardest to spot.

Check your .dockerignore:

cat .dockerignore

A .dockerignore like this will cause problems:

# This excludes EVERYTHING, then only allows certain files back
*
!Dockerfile
!src/

If you later add COPY package.json . to your Dockerfile, it will fail because package.json is excluded by the * rule.

Fix it by adding the file to the allow list:

*
!Dockerfile
!src/
!package.json

Common .dockerignore traps:

# This excludes all .env files, including ones you might need
*.env

# This excludes nested directories you might not expect
**/node_modules
**/dist

# This excludes everything starting with "build" -- including your build scripts
build*

Tip: The .dockerignore file must be in the root of the build context. If you use -f to specify a Dockerfile in a subdirectory, the .dockerignore still needs to be at the context root. (BuildKit also supports a <Dockerfile>.dockerignore convention — e.g., docker/Dockerfile.dockerignore — but the standard location is the context root.)

Fix 3: Fix COPY/ADD Source Paths

Paths in COPY and ADD are relative to the build context root, not relative to the Dockerfile location. This catches people who put their Dockerfile in a subdirectory.

Given this structure:

project/
├── docker/
│   └── Dockerfile
├── src/
│   └── app.js
└── package.json

If you build with:

docker build -f docker/Dockerfile .

Then inside docker/Dockerfile, paths are relative to project/ (the context root), not docker/:

# ❌ Wrong -- trying to go up from Dockerfile location
COPY ../src/app.js .

# ❌ Wrong -- using absolute path
COPY /src/app.js .

# ✅ Correct -- relative to build context root
COPY src/app.js .
COPY package.json .

COPY paths never use .. to navigate relative to the Dockerfile. They always start from the build context root, regardless of where the Dockerfile is located.

Fix 4: Fix Dockerfile Location

If the error is specifically:

failed to read dockerfile: open Dockerfile: no such file or directory

Docker can’t find the Dockerfile itself. Common causes:

Wrong filename or casing:

ls Dockerfile*
# Is it named "dockerfile", "DockerFile", or "Dockerfile.dev"?

Docker expects Dockerfile (capital D, no extension) by default.

Dockerfile is in a subdirectory:

# Tell Docker where the Dockerfile is
docker build -f path/to/Dockerfile .

You’re in the wrong directory:

pwd
# Make sure you're where you think you are
ls Dockerfile

Fix 5: Check Case Sensitivity

Docker builds on Linux use a case-sensitive filesystem. If you develop on macOS or Windows (case-insensitive by default), a build might work locally but fail in CI or on a Linux build server because of casing mismatches.

# Your file is named "Readme.md"
COPY README.md .  # ❌ fails on Linux -- "README.md""Readme.md"

Check the exact casing of your files:

ls -la

This also applies to directory names:

COPY Src/ ./src/   # ❌ if the directory is actually named "src/"
COPY src/ ./src/   # ✅

Fix the casing in your Dockerfile to match the actual filenames exactly.

Edge Cases

Multi-stage builds and COPY —from

In a multi-stage build, COPY --from copies from a previous build stage, not from the build context:

FROM node:20 AS builder
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
RUN npm run build

FROM nginx:alpine
# This copies from the "builder" stage, not the build context
COPY --from=builder /app/dist /usr/share/nginx/html

If you get a “file not found” error on a COPY --from line, the problem is in the earlier stage. The file wasn’t created where you expected. Add a RUN ls -la /app/dist after your build step in the builder stage to verify the files exist.

You can also copy from external images:

COPY --from=nginx:alpine /etc/nginx/nginx.conf /etc/nginx/nginx.conf

If this fails, the file path inside that image may have changed between versions.

Docker does not follow symlinks that point outside the build context. If you have:

project/
├── Dockerfile
├── config -> /etc/shared/config   # symlink to outside the context

COPY config/ . will fail because the symlink target is outside the build context. Copy the actual files into your project directory instead, or mount them at runtime with -v.

Git submodules not cloned

If your project uses git submodules and you cloned without --recurse-submodules (or if you’re not inside a Git repo at all — see Fix: fatal: not a git repository), those directories will be empty:

git clone https://github.com/user/repo.git
# submodule directories exist but are empty

docker build .
# COPY libs/shared-utils/ . → fails, directory is empty

Fix:

git submodule update --init --recursive

Then rebuild.

Docker BuildKit vs legacy builder

The error messages differ depending on which builder you’re using.

Legacy builder:

COPY failed: stat /var/lib/docker/tmp/docker-builder123456/myfile: no such file or directory

BuildKit (default since Docker 23.0):

failed to compute cache key: failed to calculate checksum of "/myfile": not found

Both mean the same thing — the file isn’t in the build context. BuildKit is now the default, so if you’re searching Stack Overflow and see the older stat /var/lib/docker/tmp error format, the same fixes apply.

You can explicitly switch between them:

# Force BuildKit
DOCKER_BUILDKIT=1 docker build .

# Force legacy builder (if still available)
DOCKER_BUILDKIT=0 docker build .

Still Not Working?

Clear Docker build cache

Docker caches build layers aggressively. If you’ve fixed the file issue but still get the error, a stale cache may be the culprit:

docker build --no-cache -t myapp .

To clear the entire build cache:

docker builder prune

WSL2 file path issues

If you’re using Docker Desktop with WSL2 on Windows, file paths between the Windows filesystem and WSL2 can cause problems.

Key rule: Keep your project files inside the WSL2 filesystem (/home/user/...), not on the Windows mount (/mnt/c/...). Files on the Windows mount are accessed through a translation layer that can cause path resolution issues, and build performance is significantly worse.

# ❌ Slow and can cause path issues
cd /mnt/c/Users/me/projects/myapp
docker build .

# ✅ Fast and reliable
cd ~/projects/myapp
docker build .

If you must use files from the Windows filesystem, make sure Docker Desktop has the correct WSL2 integration enabled under Settings > Resources > WSL Integration.

Permission denied on COPY

If the file exists but you get a permission error during COPY:

failed to solve: failed to read dockerfile: permission denied

Check the file permissions:

ls -la Dockerfile
# Make sure it's readable
chmod 644 Dockerfile

This can also happen if Docker doesn’t have access to the directory. On SELinux-enabled systems (Fedora, RHEL), you may need to adjust the security context. If the permission error is about the Docker socket itself, see Fix: Docker permission denied on the daemon socket.

Large build context slowing builds

If your build takes a long time before it even starts, Docker is sending a massive build context to the daemon. You’ll see:

Sending build context to Docker daemon  2.5GB

This usually means node_modules, .git, or large data directories are being included. Fix it with a proper .dockerignore:

node_modules
.git
*.log
dist
.next
.cache
tmp
coverage

A good .dockerignore can cut your build context from gigabytes to megabytes and dramatically speed up builds.


Related: Fix: Docker Permission Denied While Trying to Connect to the Docker Daemon Socket

Related Articles