1023 words
5 minutes

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

2026-08-14
DevOps
Docker
/
DevOps
/
Containers
/
Troubleshooting

The Docker error COPY failed: file not found in build context has a narrow meaning: the source path is not available inside the build context, or a .dockerignore rule removed it before the build started. The Dockerfile’s directory is not automatically the context.

Fix the command first. The final positional path passed to docker build defines the context; -f only selects the Dockerfile. Once that boundary is correct, make the COPY source relative to the context root and check the context’s .dockerignore file.

The build command defines the context#

Docker’s build context documentation defines a context as the set of files the builder can access. In this command:

Terminal window
docker build -f docker/Dockerfile .

. is the context, so COPY can read files under the current repository directory. docker/Dockerfile is only the Dockerfile location.

In this command:

Terminal window
docker build -f apps/web/Dockerfile apps/web

apps/web is the context. A COPY package.json . instruction now looks for apps/web/package.json, while a source such as COPY package.json /app/ cannot read a package file that lives at the repository root. Moving the Dockerfile does not expand the files available to the builder.

That distinction explains many errors that look like a typo in COPY. If the source is outside the context, changing COPY ../package.json will not make it legal. Docker deliberately prevents a Dockerfile from reaching above the context boundary.

Check .dockerignore before changing COPY#

Docker reads .dockerignore from the root of the build context. The file can exclude a path that exists on disk, so a repository listing alone is not enough to prove that Docker can copy it.

For example, with this layout:

.
├── .dockerignore
├── package.json
├── pnpm-lock.yaml
├── apps/
│ └── web/
│ ├── Dockerfile
│ └── src/

and this command:

Terminal window
docker build -f apps/web/Dockerfile .

the Dockerfile can use repository-root files:

FROM node:22-alpine AS build
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
COPY apps/web ./apps/web

But a .dockerignore rule such as apps/web or **/src can remove the exact source needed by the second COPY. Docker’s copy-ignored-file build check documents this failure mode explicitly: a COPY or ADD source that is excluded by .dockerignore is unavailable to the instruction.

Inspect the ignore file at the context root, not only beside the Dockerfile:

Terminal window
sed -n '1,240p' .dockerignore

Then check whether the pattern excludes the source or a parent directory. Remove or narrow the rule only if the file belongs in the image. Excluding secrets, local build output, and dependency directories is usually intentional; the fix is to copy the required source or build artifact explicitly, not to remove every ignore rule.

A reliable diagnosis sequence#

Use the same working directory and command that CI uses:

  1. Print the context. Identify the final path argument after all flags. Resolve it to an absolute directory.
  2. Locate the source from that root. If the Dockerfile says COPY apps/web/package.json ./, verify that the file is at <context>/apps/web/package.json.
  3. Read the context-root .dockerignore. Search for the source path and parent-directory patterns.
  4. Check case exactly. Linux builders distinguish Package.json from package.json, even when a local macOS filesystem appears less strict.
  5. Use one explicit build command. Do not debug a local root context while CI uses a subdirectory context.
  6. Re-check the next COPY. Fixing the first missing source can expose another path that is outside the same boundary.

The Docker CLI reference describes the positional PATH, URL, or - argument as the build context and notes that paths outside it cannot be used by COPY. Keep that boundary in the build command rather than relying on a developer’s current directory by accident.

Choose a context that matches the build#

There are two common layouts, and each is valid when the COPY paths match it.

Repository-root context#

Use this for a monorepo or a build that needs a root lockfile:

Terminal window
docker build -f apps/web/Dockerfile .

The Dockerfile can copy package.json, a root lockfile, and apps/web using paths from the repository root. This is also the usual shape for an Astro static build that later serves output through Caddy; the Astro and Caddy Docker guide covers that multi-stage structure.

Application-directory context#

Use this when the application is self-contained:

Terminal window
docker build -f Dockerfile apps/web

Now every source path in the Dockerfile is relative to apps/web. COPY src ./src is valid, while COPY apps/web/src ./src points to a nested path that probably does not exist. If the application needs files from the repository root, either make the root the context or change the build inputs so the application is self-contained.

The right choice is the smallest context that contains all declared build inputs. A smaller context can also reduce accidental file exposure and transfer time, but do not claim that a smaller context alone fixes a missing file; the Dockerfile and ignore rules still have to agree.

Avoid the tempting fixes#

  • Do not use ../ in COPY to escape the context. Docker filters paths outside the context.
  • Do not move the Dockerfile and assume the context moved with it.
  • Do not delete .dockerignore wholesale just to make a build pass.
  • Do not make a local command use . while a deployment script uses a nested context.
  • Do not copy the entire repository when a specific source path or generated artifact is sufficient.

If the missing file is generated, make that generation step happen before docker build and verify the generated file is not ignored. If the file is a secret, inject it through the supported build or runtime secret mechanism rather than copying it into an image layer.

FAQ#

Q: Does Docker resolve COPY paths relative to the Dockerfile?#

A: No. COPY sources are resolved from the root of the build context. The -f option selects a Dockerfile but does not redefine that root.

Q: Why can Docker see a file locally but not in the build?#

A: The build may use a different context, or .dockerignore may exclude the file. Compare the exact command and inspect the ignore file at the context root.

Q: Can I copy a parent-directory file with COPY ../file?#

A: No. A Dockerfile cannot use COPY to reach outside its build context. Choose a context that contains the file or pass it into the build through an appropriate input.

Q: Should I remove .dockerignore to fix the error?#

A: Usually not. Find the rule excluding the required source and narrow it. Keep rules that prevent secrets, dependency folders, and unrelated local files from entering the context.

References:

Docker COPY Failed: Fix “File Not Found in Build Context”
https://laplusda.com/en/posts/docker-copy-failed-file-not-found-build-context/
Author
Zero
Published at
2026-08-14
License
CC BY-NC-SA 4.0
Was this article useful?

Report a typo or broken link, or suggest a related topic.