Chapter 08Lesson 02~120 minutes

Build Contexts, .dockerignore, Remote Contexts, Named Contexts, and Deterministic Build Inputs: Guided Hands-On Workflow and Core Operations

Build and measure a small disposable project, minimize its default context, demonstrate Dockerfile-specific ignore behavior, introduce a named context, and capture plain BuildKit progress so the exact input boundary is visible rather than assumed.

Hands-on.dockerignorePlain progressNamed contextInput evidence

Learning objectives

  • Measure a disposable local context before and after excluding unnecessary files.
  • Demonstrate Dockerfile-specific ignore-file precedence with a bounded, synthetic project.
  • Use a named context to expose a second source tree without broadening the default context.
  • Capture BuildKit plain progress and actual Engine/Buildx/BuildKit/frontend versions as evidence.
  • Model a pinned Git source locally and show the current checksum-verification syntax as an optional network-capable path.
Chapter 08 evidence baseline — verified 2026-09-21. Mandatory exercises use synthetic local source, fake credential-shaped data, disposable chapter-owned images, and no production repositories or credentials. Docker Engine 29.8.1 is the current Engine 29 patch baseline at verification time; current packaging/release evidence also places Buildx 0.37.1 and BuildKit 0.33.0 in the present toolchain stream. Current Docker documentation defines build context as the files/source a builder may access, documents Dockerfile-specific ignore precedence, recommends structured Git URL queries, and supports checksum/commit verification plus named contexts. Because these capabilities are version-sensitive, every executable lab captures the actual Engine/CLI/Buildx/builder/frontend state and provides a local simulation path when network or compatible remote-Git-query support is unavailable.

1. Lab scope: measure before optimizing

This lab creates a synthetic project with one application file, one documentation file, harmless noise, fake credential-shaped data, and generated output. The goal is to prove which files are in the default context and which are isolated in a named context. Nothing is pushed to a registry and no production source or credential is used.

2. Preflight: record the builder and feature baseline

mkdir -p ch08-lab/{app,docs,noise,evidence}
cd ch08-lab

docker context show | tee evidence/00-context.txt
docker version | tee evidence/01-version.txt
docker buildx version | tee evidence/02-buildx.txt
docker buildx inspect --bootstrap | tee evidence/03-builder.txt

If buildx inspect cannot bootstrap a disposable/local builder, record that limitation and use the default builder. Do not create a privileged shared builder merely to match the example.

3. Create synthetic inputs and a deliberately noisy repository

printf 'hello from bounded context\n' > app/message.txt
printf '# documentation\nonly through named context\n' > docs/readme.md
printf 'harmless-cache-%s\n' "$(date +%s)" > noise/large.tmp
printf 'FAKE_TOKEN=not-a-secret\n' > .env
mkdir -p .git-simulation dist node_modules
printf 'fake git metadata\n' > .git-simulation/HEAD
printf 'generated output\n' > dist/output.txt
printf 'dependency tree\n' > node_modules/dependency.txt
find . -maxdepth 2 -type f -print | sort | tee evidence/04-files-before.txt
du -sh . | tee evidence/05-directory-size.txt

The .env value is intentionally fake. It exists only to demonstrate why credential-shaped files should never be present in the build input unless explicitly needed through a safer mechanism.

4. Write a Dockerfile that consumes only the intended application input

# syntax=docker/dockerfile:1
FROM busybox:1.37.0
WORKDIR /app
COPY app/message.txt ./message.txt
CMD ["cat", "/app/message.txt"]

The Dockerfile references only one file, but without an ignore file the entire local context is still eligible for transfer/snapshotting. That difference is the central lesson.

5. Capture the unoptimized context evidence

docker buildx build --progress=plain --load \
  --label devops-academy.lab=ch08-before \
  -t devops-academy-ch08:before . 2>&1 | tee evidence/06-build-before.txt

docker image inspect devops-academy-ch08:before --format 'ImageID={{.Id}}' \
  | tee evidence/07-image-before.txt

In the plain progress output, locate the step that transfers or loads the build context. Record the bytes shown by your builder. Different BuildKit versions/drivers format the line differently; preserve the actual output rather than inventing a number.

6. Minimize the default context explicitly

# .dockerignore
.env
.git
.git-simulation
node_modules
dist
noise
docs
evidence
*.log
docker buildx build --progress=plain --load \
  --label devops-academy.lab=ch08-minimal \
  -t devops-academy-ch08:minimal . 2>&1 | tee evidence/08-build-minimal.txt

docker image inspect devops-academy-ch08:minimal --format 'ImageID={{.Id}}' \
  | tee evidence/09-image-minimal.txt

Compare the context-load lines from the two builds. The image payload should still contain the same application message, but the builder should no longer need the excluded trees.

7. Demonstrate Dockerfile-specific ignore precedence

# docs.Dockerfile
# syntax=docker/dockerfile:1
FROM busybox:1.37.0
WORKDIR /site
COPY docs/readme.md ./readme.md
CMD ["cat", "/site/readme.md"]
# docs.Dockerfile.dockerignore
.env
.git*
node_modules
dist
noise
evidence
app
docker buildx build --progress=plain --load \
  -f docs.Dockerfile -t devops-academy-ch08:docs . \
  2>&1 | tee evidence/10-docs-specific-ignore.txt

Because docs.Dockerfile.dockerignore is associated with docs.Dockerfile, it governs that build instead of the root ignore file. The root file excluded docs/; the Dockerfile-specific file intentionally allows it.

8. Move documentation into an explicit named context

# named.Dockerfile
# syntax=docker/dockerfile:1
FROM busybox:1.37.0
WORKDIR /app
COPY app/message.txt ./message.txt
COPY --from=docs /readme.md ./docs/readme.md
CMD ["sh", "-c", "cat /app/message.txt; cat /app/docs/readme.md"]
docker buildx build --progress=plain --load \
  -f named.Dockerfile \
  --build-context docs=./docs \
  -t devops-academy-ch08:named . \
  2>&1 | tee evidence/11-named-context.txt

docker run --rm devops-academy-ch08:named | tee evidence/12-named-runtime.txt

The default context remains narrow while docs is exposed as a separate source. Record both the default-context and named-context lines from BuildKit progress.

9. Simulate a pinned Git source without requiring network access

git init source-repo
printf 'pinned source\n' > source-repo/source.txt
git -C source-repo add source.txt
git -C source-repo -c user.name='DevOps Academy' -c user.email='academy@example.invalid' commit -m 'lab source'
SRC_SHA=$(git -C source-repo rev-parse HEAD)
printf 'source_commit=%s\n' "$SRC_SHA" | tee evidence/13-local-git-source.txt

This local repository supplies immutable revision evidence without a remote dependency. When network access and compatible Buildx/Dockerfile versions are available, the equivalent remote pattern is a Git URL query that combines a human-readable tag/branch/ref with checksum=$SRC_SHA.

10. Challenge: locate the ownership layer

A build run on a remote builder reports COPY failed: file not found for ../shared/config.json. Decide whether to fix the Dockerfile path, widen the default context, or add an explicit named context. Explain why a client-relative path outside the context cannot simply be assumed to exist on the builder.

11. Exact cleanup

docker image rm \
  devops-academy-ch08:before \
  devops-academy-ch08:minimal \
  devops-academy-ch08:docs \
  devops-academy-ch08:named

docker image ls --filter label=devops-academy.lab=ch08-before
docker image ls --filter label=devops-academy.lab=ch08-minimal

Do not use broad image/system prune. Preserve evidence/ and the synthetic source files if you want to compare them in the checkpoint.

Next lesson

Next: Configuration, Design Choices, and Tradeoffs

Choose the right context design for local development, CI, remote builders, and release evidence.

Knowledge check

Why can a build transfer files that no COPY instruction uses?

What evidence should you preserve when comparing context size?

Why is the local Git simulation still useful?

What does --build-context docs=./docs change?

Why should the evidence packet record actual feature versions?

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 .dockerignore reduces unnecessary input.
  • Dockerfile reference — how COPY, ADD, and RUN --mount consume 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 and compatibility note

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.