Docker COPY Failed: Fix “File Not Found in Build Context”
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:
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:
docker build -f apps/web/Dockerfile apps/webapps/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:
docker build -f apps/web/Dockerfile .the Dockerfile can use repository-root files:
FROM node:22-alpine AS buildWORKDIR /app
COPY package.json pnpm-lock.yaml ./COPY apps/web ./apps/webBut 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:
sed -n '1,240p' .dockerignoreThen 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:
- Print the context. Identify the final path argument after all flags. Resolve it to an absolute directory.
- 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. - Read the context-root
.dockerignore. Search for the source path and parent-directory patterns. - Check case exactly. Linux builders distinguish
Package.jsonfrompackage.json, even when a local macOS filesystem appears less strict. - Use one explicit build command. Do not debug a local root context while CI uses a subdirectory context.
- 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:
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:
docker build -f Dockerfile apps/webNow 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
../inCOPYto escape the context. Docker filters paths outside the context. - Do not move the Dockerfile and assume the context moved with it.
- Do not delete
.dockerignorewholesale 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:
Report a typo or broken link, or suggest a related topic.