[Fixed] Docker: COPY failed: file not found in build context: Step-by-Step Troubleshooting Guide

Quick Summary: The error COPY failed: file not found in build context (or BuildKit error failed to solve: failed to compute cache key: failed to calculate checksum of ref: "<path>" not found) occurs during docker build when the Docker CLI cannot locate a source file referenced by a COPY or ADD instruction. This stems from misunderstanding Docker’s build context directory, passing incorrect relative paths when using -f <path/to/Dockerfile>, overzealous ignore rules in .dockerignore, or case-sensitivity mismatches between host operating systems and Linux container engines.

Understanding the Root Causes

When you trigger docker build, the CLI packs the designated context directory (usually specified by the trailing .) into a tarball and transfers it to the Docker daemon or BuildKit worker. Instructions like COPY <src> <dest> search strictly within this unpacked context. The build fails if:

  • Attempting to Copy Outside the Context Root: Executing COPY ../shared /app. Docker intentionally forbids traversing above the build context root (e.g., via ../) for host security reasons.
  • Relative Path Confusion with Custom Dockerfile Locations: When passing -f docker/Dockerfile ., source paths in COPY instructions remain relative to the build context root (.), not to the docker/ subfolder where the Dockerfile resides.
  • Overly Broad .dockerignore Exclusions: Wildcards like *, *.json, or build/ in .dockerignore discarding required build artifacts before the context reaches the daemon.
  • Filesystem Case-Sensitivity Discrepancies: File names formatted as Index.js on case-insensitive macOS/Windows host filesystems failing against Linux Docker daemons expecting exact casing (index.js).

Step 1: Quick Fix – Set Context Root Correctly with the -f Flag

If your Dockerfile lives in a subfolder or you need files from parent directories, specify the repository root as the build context while pointing to the Dockerfile with -f:

# Incorrect: Building inside the subfolder isolates the context from parent files
cd backend && docker build -t myapp .

# Correct: Run from repository root and point -f to the nested Dockerfile
docker build -f backend/Dockerfile -t myapp .

# In docker-compose.yml:
services:
  web:
    build:
      context: .                 # Context is repository root
      dockerfile: backend/Dockerfile # Path to Dockerfile relative to context

Step 2: Inspect and Refine .dockerignore Rules

Check if your .dockerignore file accidentally excludes the file you are attempting to copy. Use explicit exception syntax (!) if necessary:

# Inspect the .dockerignore file
cat .dockerignore

# If you ignore all JSON files or node_modules:
# *.json
# node_modules

# Ensure required configuration files are explicitly whitelisted:
!package.json
!package-lock.json

# If ignoring a directory but needing specific contents:
dist/*
!dist/bundle.js

Step 3: Multi-Stage Copy and Named Build Contexts

If the file is generated during an earlier build stage or belongs to an external directory, use multi-stage build flags or BuildKit additional contexts:

# Option A: Copying artifacts from an earlier named stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Final production stage
FROM nginx:alpine
# Copy compiled output from the 'builder' stage, NOT the host context
COPY --from=builder /app/dist /usr/share/nginx/html

# Option B: Using BuildKit named contexts for external directories (Docker 20.10+)
# CLI: docker build --build-context shared=../shared -t myapp .
# Dockerfile:
# COPY --from=shared . /app/shared

Verification & Testing Steps

Audit the files actually present within your Docker build context to confirm availability before running full compilation:

# Temporarily test build context contents by running a scratch inspection
docker build --no-cache -t context-test -f - . <<EOF
FROM alpine
WORKDIR /context
COPY . .
RUN ls -la && find . -name "package.json"
EOF

# Clean up test image
docker rmi context-test

# Verify target file casing on your host terminal
find . -iname "package.json"

Troubleshooting Summary Comparison

Failure Scenario Root Cause Recommended Solution
COPY ../file.txt fails Cannot reference paths outside context Move context root to parent (docker build -f sub/Dockerfile .)
File exists locally but missing in build Filtered out by .dockerignore Add whitelist rule (!file.txt) to .dockerignore
Works on macOS, fails on Linux/CI Case sensitivity mismatch Match exact casing between host filename and COPY command
Copying compiled artifacts Artifact only exists in builder image Use COPY --from=<stage_name> <src> <dest>

Leave a Reply