TL;DR
Docker can't find the file you're trying to COPY. Simple as that. Three things cause this 9 times out of 10: running docker build from the wrong directory, a bad path in your COPY instruction, or a .dockerignore rule silently excluding it.
Quick checklist:
- Run
docker buildfrom the directory that contains yourDockerfileand source files. - Confirm the file actually exists:
ls app.py - Check
.dockerignoreโ the file might be excluded there. - Double-check the path inside the
COPYinstruction.
What This Error Means
When you run docker build, Docker packages up a build context โ the directory you point it to, usually . โ and ships it to the Docker daemon. That daemon has no direct access to your local filesystem. The COPY instruction can only touch files that made it into that bundle.
The full error looks like this:
COPY failed: file not found in build context or excluded by .dockerignore: stat app.py: file does not exist
Two possibilities: app.py isn't in the build context at all, or a .dockerignore pattern is filtering it out before Docker even processes your instructions.
Root Cause 1: Wrong Build Context Directory
This is the most common cause. If your project looks like this:
my-project/
โโโ src/
โ โโโ app.py
โโโ docker/
โโโ Dockerfile
And your Dockerfile says:
COPY app.py /app/app.py
Then running this from inside docker/ will fail:
cd my-project/docker
docker build .
app.py lives in my-project/src/, not in my-project/docker/. Docker only sees what's in the context you gave it โ nothing outside.
Fix
Run the build from the project root and point to the Dockerfile explicitly:
cd my-project
docker build -f docker/Dockerfile .
Or update the COPY path to match the directory you're actually building from:
# If building from my-project/
COPY src/app.py /app/app.py
Root Cause 2: File Simply Doesn't Exist
Start with the basics. Is the file actually there?
ls -la app.py
No such file or directory means exactly what it says. A few common reasons:
- You forgot to create the file before building.
- There's a typo in the filename โ
App.pyvsapp.py. Linux is case-sensitive. - The file is on a different branch and you haven't checked it out yet.
Fix
Create or rename the file, then rebuild. To catch typos, list everything in the directory:
ls -la
If the file is on another branch:
git checkout main -- app.py
Root Cause 3: File Excluded by .dockerignore
The .dockerignore file works like .gitignore โ any file matching a pattern gets stripped from the build context before Docker even sees it. The tricky part: Docker won't warn you. It quietly removes the file and moves on.
Check your .dockerignore:
cat .dockerignore
Look for patterns that could match your file. For example:
# This would exclude app.py
*.py
# This would also exclude app.py if it's inside a directory
src/
# Or a wildcard that's too broad
*
Fix
Either remove the matching pattern, or add an exception using !:
# Exclude all .py files but keep app.py
*.py
!app.py
To inspect what's actually included in your build context without a full build:
docker build --no-cache --progress=plain . 2>&1 | head -30
Root Cause 4: Wrong Path in the COPY Instruction
The source path in COPY is always relative to the build context root โ not the Dockerfile's location. This catches people off guard when the Dockerfile lives inside a subdirectory.
Given this structure:
my-project/
โโโ app.py
โโโ Dockerfile
Building from my-project/:
# Correct
COPY app.py /app/app.py
# Wrong โ no leading slash in the source path
COPY /app.py /app/app.py
Also watch out for referencing a subdirectory that doesn't exist at the build context root:
# Wrong if src/ doesn't exist at the build context root
COPY src/app.py /app/app.py
Root Cause 5: Building from a Remote Git URL
Less common, but worth knowing. If you pass a remote Git URL as the build context:
docker build https://github.com/user/repo.git
Docker clones the repo and uses it as the build context. Files not committed to Git โ anything in .gitignore, anything you forgot to git add โ simply don't exist from Docker's perspective. Check that the file is both committed and pushed to the branch you're building from.
Verification: Confirm Your Fix Worked
Rebuild and watch the output:
docker build -t myapp:test .
A successful COPY step looks like this:
=> [2/3] COPY app.py /app/app.py 0.0s
That 0.0s on the right means it was read from cache or disk instantly. No error after that line โ you're good.
Want to confirm the file actually made it inside the image?
docker run --rm myapp:test ls /app/
You should see app.py listed in the output.
Quick Diagnostic Commands
# Check what directory you're in
pwd
# List files in current directory
ls -la
# View your .dockerignore (if it exists)
cat .dockerignore
# Build with verbose output to see what's in context
docker build --progress=plain . 2>&1 | grep -E '(COPY|STEP|Error)'
# Verify the file is in the built image
docker run --rm ls /path/to/destination/

