KhueApps
Home/DevOps/Fix Docker COPY failed: file not found or excluded by .dockerignore

Fix Docker COPY failed: file not found or excluded by .dockerignore

Last updated: October 06, 2025

What this error means

When building an image, Docker sends a “build context” (files under the chosen directory, minus anything excluded by .dockerignore). COPY can only read from that context. If the source path doesn’t exist in the context, you’ll see:

COPY failed: file not found in build context or excluded by .dockerignore

Common causes:

  • Running docker build from the wrong directory (wrong context)
  • Path mismatch in COPY (relative paths, case sensitivity)
  • .dockerignore excludes the file or directory
  • Misusing -f Dockerfile path vs. build context path
  • Multi-stage COPY --from using a path that doesn’t exist in that stage

Quickstart checklist (fast fixes)

  1. Run the build from the directory that contains the files you COPY.
    • Example: docker build -t myimg .
  2. If your Dockerfile is elsewhere, keep the context correct:
    • docker build -f path/to/Dockerfile path/to/context
  3. Verify the source path in COPY matches your repo layout (relative to context).
  4. Inspect .dockerignore for patterns excluding your files; remove or negate them.
  5. On case-sensitive systems (Linux), ensure exact casing in file and COPY path.
  6. For multi-stage, ensure the source exists in that stage: COPY --from=builder /out/app ./app

Minimal working example (MWE)

This example succeeds and demonstrates correct context, paths, and .dockerignore.

Files:

  • Dockerfile
  • src/hello.txt
  • .dockerignore (empty or not excluding src)

Dockerfile:

FROM alpine:3.20
WORKDIR /app
# Copy from a directory that exists in the build context
COPY src/ ./src/
# Prove the file was copied
RUN test -f ./src/hello.txt
CMD ["sh", "-c", "cat ./src/hello.txt"]

.dockerignore (optional, empty for MWE):

# keep empty or avoid excluding src/

Build and run:

printf "hello\n" > src/hello.txt
docker build -t mwe .
docker run --rm mwe

Expected output:

hello

Reproduce the error and fix it

Error reproduction: exclude src/ in .dockerignore.

.dockerignore (bad):

src/

Build:

docker build -t broken .

Expected error:

COPY failed: file not found in build context or excluded by .dockerignore

Fix options:

  • Remove the exclusion, or
  • Narrow it, or
  • Negate it to re-include specific files

.dockerignore (fixed, re-include hello.txt):

src/
!src/hello.txt

Alternatively, change Dockerfile paths to copy from a non-excluded directory.

Step-by-step diagnosis

  1. Confirm your build context
    • Run docker build in the directory that contains your sources.
    • If using -f, set the second argument to the intended context:
      • docker build -f docker/prod/Dockerfile .
      • docker build -f Dockerfile ./subdir
  2. Verify COPY source paths
    • Paths are relative to the context, not the Dockerfile (unless you set -f inside the context). Avoid leading slashes.
    • Example: if file is at app/src/index.js and context is repo root, use COPY app/src/index.js /app/
  3. Inspect .dockerignore
    • Look for broad patterns like node_modules, dist, build, .* that may exclude needed files.
    • Use negation (!) to re-include specific paths; order matters (negations must come after the exclusion).
  4. Check case and platform details
    • Linux is case-sensitive; Windows/macOS filesystems may be case-insensitive. Keep consistent casing in repo and COPY.
  5. Multi-stage build verification
    • For COPY --from=builder, ensure the path exists inside that stage’s filesystem, not the local context.
    • Add a debug line: RUN ls -la /expected/path in the source stage.
  6. Ensure files exist before COPY
    • Generated files must be present in context or created in a prior stage. You cannot COPY artifacts built on the host during the build unless they’re in the context and not ignored.

Common pitfalls

  • Using absolute paths in COPY (e.g., COPY /file /dest) — source must be relative to context.
  • Dockerfile outside context without correct -f and context arguments.
  • .dockerignore too broad (e.g., src/, **/*.json) removing required files.
  • Relying on host-only artifacts (e.g., files generated by a pre-build script) that aren’t committed or placed inside the context.
  • Incorrect negation order in .dockerignore (negations must come after the rule they negate).
  • Copying from a previous stage but the stage name is wrong or path missing.

Cause-to-fix cheat sheet

CauseHow to detectFix
Wrong build contextdocker build shows small context or missing filesRun from repo root or pass correct context path
Path mismatchls shows file path differs from COPY sourceAdjust COPY to correct relative path
Excluded by .dockerignorePattern matches the missing pathRemove pattern, narrow it, or use ! negation
Dockerfile path confusionUsing -f without correct contextdocker build -f path/to/Dockerfile path/to/context
Multi-stage path missingRUN ls in source stage shows path absentCreate the file in the stage or correct COPY --from path

Performance notes

  • Use .dockerignore to shrink context (e.g., .git, node_modules, dist, coverage). Smaller contexts upload faster and cache more effectively.
  • Keep required sources unignored; when in doubt, re-include small subsets with negation (e.g., !src/config/*.json).
  • Optimize caching by copying dependency manifests first, then running installs, then COPY the rest. Example for Node.js:
COPY package*.json ./
RUN npm ci --only=production
COPY . .
  • Prefer multi-stage builds to avoid copying large toolchains/artifacts into the final image.
  • Use docker build --progress=plain to see context size and layer cache info.

Tiny FAQ

  • Can I COPY files outside the build context?
    • No. Docker only sees files under the context directory.
  • How do I build when my Dockerfile is in a subfolder?
    • docker build -f subdir/Dockerfile . (context is current dir), or docker build -f subdir/Dockerfile subdir (context is subdir).
  • Do .dockerignore patterns support negation?
    • Yes. Use !pattern to re-include. Order matters; negations must come after the exclude.
  • Why does it work on my machine but fail in CI?
    • CI may run from a different context or use a different .dockerignore set. Explicitly set -f and context, and audit .dockerignore.
  • COPY from a stage still fails — is that the same error?
    • Similar symptom, different cause: the file must exist in the source stage’s filesystem. Add RUN ls in that stage to verify.

Series: Docker

DevOps