01
Read the build command as well as the Dockerfile
In docker build -f docker/Dockerfile ., the final dot supplies the context. The Dockerfile lives under docker, but that does not automatically make docker the root of its COPY source paths. Compare the actual CI command with the one that works locally.
A missing source can fail while the builder computes a checksum or cache key, before the copy is executed. That wording can suggest cache corruption, yet the root issue may still be that the source never entered the context.
02
Make the contradiction reproducible
Create a new directory containing message.txt with the text context-ok, the Dockerfile below, and a .dockerignore file containing message.txt. The file exists on the host but is deliberately excluded from the build input.
Building this directory should fail at COPY. In our validation it did. Repeating the build with no cache would not restore an excluded source, so investigate the input rather than treating every checksum error as stale cache.
FROM python:3.12-slim
COPY message.txt /app/message.txt03
Compare host existence with context eligibility
Run the following from the new example directory. If a real file is missing, confirm case and spelling as well as the location of the context root. A case-insensitive development filesystem can conceal a mismatch that appears on Linux.
Inspect applicable ignore files, including any Dockerfile-specific ignore file used by your layout. A broad pattern may remove a required build artifact even though the application source remains available.
printf 'context-ok\n' > message.txt
printf 'message.txt\n' > .dockerignore
ls -l message.txt
cat .dockerignore
# Expected failure: message.txt was excluded.
docker build --tag copy-proof .04
Repair the narrow input rule
In the disposable example, replace the incorrect ignore rule with .git and .env entries, then rebuild. In an actual project, preserve exclusions for credentials and unrelated files; allow only the needed build inputs rather than deleting .dockerignore entirely.
If the context itself is too narrow, pass the intended project directory and adjust source paths deliberately. Do not point a build at your whole home directory as a shortcut. That can send irrelevant or sensitive files to the builder.
printf '.git\n.env\n' > .dockerignore
docker build --tag copy-proof .
docker run --rm copy-proof cat /app/message.txt05
Verify the image, then the deployed artifact
The corrected image printed context-ok in our test. That confirms the specific source bytes arrived at the expected image path. The successful build alone is a weaker result because another stage or a different destination could still omit the runtime artifact.
For a multi-stage image, inspect the final stage separately. A host-source COPY failure and a COPY --from failure have different source locations. Finish by confirming that the service deploys the image you just verified, not an older tag from another build.
Know the limits
The example is a local directory context with BuildKit and a text file. Remote Git contexts, named contexts, multi-stage COPY --from, and symlink behavior require their own source-path investigation. Error wording and checksum messages vary by builder version. Reproduction checked on 26 October 2026 using Linux containers on Docker Engine 29.6.2 and Compose 5.3.1; this is the validation environment, not a minimum-version claim.
Sources & further reading
A technical publication by CoreTrailKit.
Browse all articles