Build Contexts, .dockerignore, Remote Contexts, Named Contexts, and Deterministic Build Inputs: Diagnostics, Failure Modes, Security, and Performance
Context failures often look like missing files, stale caches, surprising network activity, or slow builds. This lesson preserves build evidence and diagnoses leaked files, incorrect ignore assumptions, mutable Git refs, remote-builder path confusion, and accidental context expansion without destructive cleanup.
Learning objectives
- Preserve Dockerfile text, ignore rules, build command, builder identity, plain progress, source revision, and image identity before changing anything.
- Diagnose accidental .git/credential/build-output transfer, incorrect .dockerignore patterns, and Dockerfile-specific ignore precedence.
- Recognize mutable Git-ref drift and use checksum verification rather than trusting a branch or tag name alone.
- Distinguish client-side context preparation from builder-side remote fetching and filesystem access.
- Apply the smallest source-controlled correction and verify context size/input identity again.
1. Diagnostic method: preserve the input contract first
Before editing ignore rules or changing the build command, capture the failing Dockerfile, context argument, ignore files, builder identity, plain progress, source revision, and output/error. Context failures are often made harder by “trying a different directory” until the build works, which erases the original dependency mistake.
docker context show
docker version
docker buildx version
docker buildx inspect
git rev-parse HEAD 2>/dev/null || true
cat .dockerignore 2>/dev/null || true
docker buildx build --progress=plain --no-cache . 2>&1 | tee first-failure.log
--no-cache is shown only as a bounded diagnostic
comparison for a disposable lab; it is not a first-line production
fix.
2. Failure: credentials, .git data, outputs, or dependencies enter the context
Symptoms include unexpectedly large context transfer, slow remote builds, surprising cache invalidation, or secret scanners reporting files that were never meant to be part of the image. Diagnose the context boundary first: list source files, inspect root/Dockerfile-specific ignore rules, and compare the plain progress transfer line.
3. Failure: assuming .dockerignore equals
.gitignore
A pattern copied from Git may match differently than expected.
Docker preprocesses patterns, uses Go filepath-style matching,
supports **, and honors negation order. Reduce the case
to a tiny disposable tree and test one rule at a time. Keep the
explanation in the evidence packet so future maintainers know why
the pattern exists.
dist/**
!dist/release-manifest.json
The order matters: later negation can re-include an otherwise excluded path when its parent matching permits it. Test rather than assume.
4. Failure: the wrong ignore file is being read
A build using -f lint.Dockerfile may be governed by
lint.Dockerfile.dockerignore, not the root file. When a
file is unexpectedly missing—or unexpectedly present—record the
selected Dockerfile and inspect the associated ignore file before
changing COPY.
5. Failure: remote branch or tag moved
A build that succeeded yesterday can produce different source today if it uses only a mutable branch or tag. Preserve the current resolved commit and compare it to the reviewed release revision. With compatible tooling, add a checksum/commit query so the build fails when the selector points somewhere unexpected instead of silently accepting drift.
Expected selector: tag=v1.2.3
Expected commit: 0123456789abcdef...
Observed commit: fedcba9876543210...
Result: stop; investigate upstream ref movement before rebuilding
6. Failure: client path confused with builder path
Suppose the Dockerfile tries
COPY ../shared/config.json /app/. Docker prevents
escaping the context root, and a remote builder would not have a
contractual right to the client's parent path anyway. The fix is not
--privileged, a broad host bind, or copying the entire
workstation. Move the intended source under a reviewed context or
expose it as a named context.
7. Intentionally broken lab: excluded file requested by COPY
mkdir -p broken-demo/secret-like
printf 'not-a-secret\n' > broken-demo/secret-like/token.txt
cat > broken-demo/Dockerfile <<'EOF'
# syntax=docker/dockerfile:1
FROM busybox:1.37.0
COPY secret-like/token.txt /demo/token.txt
EOF
printf 'secret-like\n' > broken-demo/.dockerignore
docker buildx build --progress=plain --load -t devops-academy-ch08:broken broken-demo \
2>&1 | tee broken-demo/first-failure.log || true
The expected failure is a source-file/context error: the Dockerfile asks for a path that the ignore boundary deliberately removed. Preserve the error, then fix the design. For this synthetic case, the correct change is to decide whether the file is truly needed; because it is credential-shaped, the safer answer is not to re-include it. Replace it with a non-secret declared file or a BuildKit secret mount in a later secrets-focused lesson.
8. Performance diagnosis: measure, do not guess
Measure directory size, context-load bytes/time in plain progress, and cache reuse before changing patterns. A slow build can come from context transfer, remote source fetch, build execution, image export, registry transfer, or runtime startup. Label the layer correctly.
9. Evidence-first sequence
- Preserve the first failure and exact build command.
- Confirm context/builders and actual versions.
- Identify default and named context sources.
- Inspect root and Dockerfile-specific ignore files.
- Record Git/remote source identity and checksum expectations.
- Inspect plain BuildKit source/context steps.
- Correct only the causal input boundary.
- Rebuild the smallest disposable scope and compare evidence.
Knowledge check
A remote build cannot find ../shared/config.json.
Should you mount the client's filesystem root?
No. Define the dependency through a bounded default or named context. Broad host mounts weaken the trust boundary and do not create reproducible input ownership.
A tag-based Git build changed output without Dockerfile changes. Which evidence comes first?
Compare the resolved Git commit/source identity and then verify the tag/ref against the reviewed checksum.
Why preserve a failed COPY error before changing
.dockerignore?
The error proves the original context contract; editing first can hide whether the root cause was exclusion, wrong context root, or wrong path.
What should you measure before claiming context optimization improved performance?
At least context bytes/load time and build timing under the same builder conditions; ideally cache behavior too.
Official references and version notes
-
Build context
— authoritative behavior for local directories, Git repositories,
tarballs, stdin/empty contexts,
.dockerignore, Dockerfile-specific ignore files, Git URL queries/checksums, and named contexts. -
docker buildx build—--build-context, progress, outputs, metadata, and accepted named-context source types. -
Optimize cache usage
— why a small context improves transfer and cache behavior and how
.dockerignorereduces unnecessary input. -
Dockerfile reference
— how
COPY,ADD, andRUN --mountconsume build inputs. - Build best practices — source-control, cache, image, and reproducibility guidance.
- Docker Engine 29 release notes — current Engine baseline and fixes.
- Buildx releases — current Buildx feature/compatibility history.
- BuildKit releases — current BuildKit and built-in Dockerfile frontend releases.
Version-sensitive statements were rechecked against primary
documentation on 2026-09-21. Docker Engine 29.8.1
is the current Engine 29 patch release at this checkpoint; Buildx
0.37.1 and BuildKit 0.33.0 are current upstream baselines observed
in the current Docker packaging/release stream, and BuildKit
0.33.0 includes the built-in Dockerfile frontend 1.27.0. Docker
documents structured Git URL queries with
checksum/commit as requiring Buildx
0.28.0+, Dockerfile 1.18.0+, and Docker Desktop 4.46.0+ where
Desktop is used. Labs therefore record the learner's actual
builder/frontend state and include a local simulation path instead
of assuming remote Git-query support or network access.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.