Chapter 32Lesson 05~205 minutes

Checkpoint Lab — Storage Drivers, overlay2, Copy-on-Write Behavior, Disk Usage, Pruning, and Storage Troubleshooting

Create a known storage footprint, predict what is reclaimable, remove only labeled or exactly named disposable resources, and prove protected data remains while disk evidence changes as predicted.

CheckpointReclaimable bytesProtected dataEvidence packetChapter 33 bridge

Learning objectives

  • Create a known image/container/volume/cache/log footprint and write predictions before mutation.
  • Capture Engine, storage-backend, filesystem/accounting, builder, object, and retention evidence in one packet.
  • Protect one volume deliberately while removing only disposable lab resources.
  • Compare predicted versus observed reclaimable/delta behavior without assuming byte-for-byte equality.
  • Close Chapter 32 with a production storage runbook that bridges to daemon configuration in Chapter 33.

1. Checkpoint scenario

You will create four controlled storage sources: a synthetic image, a stopped container with a writable-layer payload, a disposable named volume, and a dedicated builder cache. A second named volume is marked protected and contains a checksum marker. You will inventory all resources, predict cleanup results, delete only the disposable set, prove the protected marker remains, and only then remove the final protected training volume as an explicit end-of-lab rollback.

2. Version/platform assumptions to record

Item Course baseline / expectation Required evidence
Engine 29.8.1 current on 2026-09-22; actual host may differ docker version
Store Fresh Engine 29: containerd image store; upgraded hosts may be classic docker info + DriverStatus
Buildx/BuildKit Bundle/builder versions vary docker buildx version + buildx inspect
Compose/containerd/runc May vary by Desktop/distribution packaging record available version evidence; do not infer host binaries equal managed components
Image alpine:3.22.1, digest recorded after pull/build image inspect/RepoDigest when available
Storage host Local Linux, remote Engine, or Docker Desktop VM differ context + OS/arch + Desktop note

3. Preflight and exact-name guards

set -eu
LAB=dca32-checkpoint
EVIDENCE="$LAB/evidence"
mkdir -p "$EVIDENCE/context"

date -u +%Y-%m-%dT%H:%M:%SZ | tee "$EVIDENCE/time.txt"
docker context show | tee "$EVIDENCE/context-name.txt"
docker version | tee "$EVIDENCE/docker-version.txt"
docker info | tee "$EVIDENCE/docker-info.txt"
docker buildx version 2>/dev/null | tee "$EVIDENCE/buildx-version.txt" || true
docker compose version 2>/dev/null | tee "$EVIDENCE/compose-version.txt" || true
docker system df | tee "$EVIDENCE/system-df-before.txt"
docker system df -v | tee "$EVIDENCE/system-df-before-verbose.txt"

for c in dca32-cp-writable; do
  if docker container inspect "$c" >/dev/null 2>&1; then echo "collision: $c" >&2; exit 1; fi
done
for v in dca32-cp-data dca32-cp-protected; do
  if docker volume inspect "$v" >/dev/null 2>&1; then echo "collision: $v" >&2; exit 1; fi
done
if docker image inspect dca32-cp-image:lab >/dev/null 2>&1; then echo 'image collision' >&2; exit 1; fi
if docker buildx inspect dca32-cp-builder >/dev/null 2>&1; then echo 'builder collision' >&2; exit 1; fi

If any guard fires, choose different training names. Do not delete the preexisting object merely to make the lab fit.

4. Storage architecture evidence

docker info --format 'root={{.DockerRootDir}} driver={{.Driver}} logging={{.LoggingDriver}}'   | tee "$EVIDENCE/storage-summary.txt"
docker info --format '{{json .DriverStatus}}'   | tee "$EVIDENCE/driver-status.json"
docker buildx ls | tee "$EVIDENCE/builders-before.txt"

Label the result: containerd snapshotter-backed, classic overlay2, Desktop-managed, or another supported backend. Do not force the host to match the course baseline.

5. Write predictions before creating storage

cat > "$EVIDENCE/predictions.md" <<'EOF'
# Predictions
1. The writable container will add roughly 7 MiB of private writable-layer data, visible in docker ps --size.
2. The disposable and protected volumes will persist independently of the writable container lifecycle.
3. The dedicated builder will own cache that can be removed by deleting that builder without pruning unrelated builders.
4. Removing the disposable container/image/data-volume/builder will reduce some Docker accounting, but exact reclaimed bytes may differ because of shared layers, compression, allocation units, and retained protected state.
5. The protected volume checksum will still verify after all disposable resources are removed.
EOF
cat "$EVIDENCE/predictions.md"

6. Create the checkpoint image and dedicated builder

mkdir -p "$LAB/context"
cat > "$LAB/context/Dockerfile" <<'EOF'
# syntax=docker/dockerfile:1
FROM alpine:3.22.1
LABEL devops-academy.lab=chapter32-checkpoint
RUN dd if=/dev/zero of=/opt/checkpoint-image.bin bs=1M count=4  && sha256sum /opt/checkpoint-image.bin > /opt/checkpoint-image.sha256
CMD ["sh", "-c", "cat /opt/checkpoint-image.sha256"]
EOF

docker buildx create --name dca32-cp-builder --driver docker-container --use
docker buildx inspect --bootstrap | tee "$EVIDENCE/builder-inspect.txt"
docker buildx build   --builder dca32-cp-builder   --load   -t dca32-cp-image:lab   --progress=plain   "$LAB/context" | tee "$EVIDENCE/build.txt"
docker image inspect dca32-cp-image:lab > "$EVIDENCE/image-inspect.json"
docker buildx du --builder dca32-cp-builder | tee "$EVIDENCE/build-cache.txt"

7. Create writable-layer and bounded-log usage

docker create \
  --name dca32-cp-writable \
  --label devops-academy.lab=chapter32-checkpoint \
  --log-driver local \
  --log-opt max-size=1m \
  --log-opt max-file=2   dca32-cp-image:lab   sh -c 'dd if=/dev/zero of=/writable.bin bs=1M count=7; for i in 1 2 3; do echo checkpoint-log-$i; done; sleep 300'

docker start dca32-cp-writable
docker logs dca32-cp-writable | tee "$EVIDENCE/container-logs.txt"
docker ps --size --filter name=dca32-cp-writable | tee "$EVIDENCE/container-size-running.txt"
docker stop dca32-cp-writable
docker inspect --size dca32-cp-writable > "$EVIDENCE/container-inspect-size.json"

8. Create disposable and protected volumes

docker volume create --label devops-academy.lab=chapter32-checkpoint dca32-cp-data
docker volume create --label devops-academy.protection=chapter32-checkpoint dca32-cp-protected

docker run \
  --rm \
  --mount type=volume,src=dca32-cp-data,dst=/data   alpine:3.22.1   sh -c 'dd if=/dev/zero of=/data/disposable.bin bs=1M count=5; sha256sum /data/disposable.bin'   | tee "$EVIDENCE/disposable-volume.txt"

docker run --rm   --mount type=volume,src=dca32-cp-protected,dst=/protected   alpine:3.22.1   sh -c 'printf "DO-NOT-DELETE-UNTIL-VERIFIED
" >/protected/marker.txt; sha256sum /protected/marker.txt'   | tee "$EVIDENCE/protected-before.txt"

The protection label is evidence of policy intent; the stronger safety mechanism is that cleanup commands below never name the protected volume until after verification.

9. Inventory populated state and estimate reclaimability

docker system df | tee "$EVIDENCE/system-df-populated.txt"
docker system df -v | tee "$EVIDENCE/system-df-populated-verbose.txt"
docker ps -a --size --filter label=devops-academy.lab=chapter32-checkpoint   | tee "$EVIDENCE/lab-containers.txt"
docker image ls --filter label=devops-academy.lab=chapter32-checkpoint   | tee "$EVIDENCE/lab-images.txt"
docker volume ls --filter label=devops-academy.lab=chapter32-checkpoint   | tee "$EVIDENCE/disposable-volumes.txt"
docker volume ls --filter label=devops-academy.protection=chapter32-checkpoint   | tee "$EVIDENCE/protected-volumes.txt"
docker buildx du --builder dca32-cp-builder   | tee "$EVIDENCE/builder-du-populated.txt"

Write your estimated reclaimable categories into $EVIDENCE/reclaim-plan.md. Do not promise exact physical bytes; state which objects are expected to disappear and why they are safe to remove.

10. Remove only disposable objects

docker rm dca32-cp-writable
docker volume rm dca32-cp-data
docker image rm dca32-cp-image:lab
docker buildx rm dca32-cp-builder

docker system df | tee "$EVIDENCE/system-df-after-disposable.txt"
docker system df -v | tee "$EVIDENCE/system-df-after-disposable-verbose.txt"

No command names the protected volume. No system/image/container/volume/build-cache prune is used.

11. Prove protected data survived

docker volume inspect dca32-cp-protected > "$EVIDENCE/protected-inspect.json"
docker run \
  --rm \
  --mount type=volume,src=dca32-cp-protected,dst=/protected,readonly   alpine:3.22.1   sh -c 'cat /protected/marker.txt; sha256sum /protected/marker.txt'   | tee "$EVIDENCE/protected-after.txt"

diff -u "$EVIDENCE/protected-before.txt" "$EVIDENCE/protected-after.txt" || true

The container IDs differ and line formatting may vary, but the marker content/checksum must remain stable. That is the checkpoint’s proof that targeted cleanup preserved protected persistent data.

12. Compare predictions with evidence

Prediction 1 — writable size:
  Evidence:
  Result: confirmed / different because ...

Prediction 2 — volume independence:
  Evidence:
  Result:

Prediction 3 — dedicated builder ownership:
  Evidence:
  Result:

Prediction 4 — Docker accounting delta:
  Evidence:
  Result:

Prediction 5 — protected checksum:
  Evidence:
  Result:

An unexpected delta is not automatically a failure. Shared layers, base-image retention, BuildKit storage ownership, compressed logs, filesystem allocation, and asynchronous VM reclamation can all make physical-byte change differ from a simple arithmetic estimate.

13. Evidence packet manifest

Evidence family Minimum contents
Environment UTC time, context, client/server versions, OS/arch, Desktop/remote note
Storage architecture DockerRootDir, Driver, DriverStatus/snapshotter interpretation, logging driver
Capacity/accounting system df before/populated/after; verbose snapshots; optional local daemon filesystem bytes+inodes
Image/container image ID/digest evidence, writable size, container state/log config
Volumes disposable/protected names, labels, checksums, retention decision
Builder Buildx version, builder driver, BuildKit inspect, buildx du
Cleanup exact commands/objects removed; explicit statement that no broad prune ran
Limitations shared bytes, Desktop VM disk reclamation, remote-context host identity, measurement timestamp

14. Final rollback of the remaining protected training volume

# Only after protected-after.txt proves the retention test succeeded:
docker volume rm dca32-cp-protected

docker system df | tee "$EVIDENCE/system-df-final.txt"

The protected volume was “protected during cleanup,” not permanent production data. Its final exact deletion returns the disposable lab to zero persistent resources while preserving the evidence directory.

15. Production storage operating model and Chapter 33 bridge

Chapter 32 adds a storage runbook to the secure Docker operating model: identify the active Engine storage architecture; monitor both bytes and inodes; measure image/content, writable-layer, volume, cache, and log state separately; protect persistent data through explicit ownership/backup; budget BuildKit cache and logs; and delete only resources whose lifecycle is understood.

Chapter 33

Daemon configuration, daemon.json, systemd, proxies, registry mirrors, live restore, and host integration

Storage troubleshooting repeatedly touched daemon-level settings but intentionally did not mutate them. Next, you will learn how to govern those host-wide settings safely: configuration precedence, validation, systemd integration, proxies, mirrors, live restore, restart impact, and rollback.

Knowledge check

Why did the checkpoint keep the protected volume while deleting the disposable set?

Why may reclaimed physical bytes differ from the sizes you created?

What evidence proves the container’s 7 MiB write belonged to its writable layer?

How did the builder design reduce cleanup risk?

Which storage invariant carries into Chapter 33?

Official references and version notes

Checkpoint baseline date:

2026-09-22. The lab is designed to work on either Engine 29 containerd image store or classic storage, and on Desktop with expected accounting differences. It never changes daemon configuration, storage driver/snapshotter, data-root, or internal Docker/containerd files.

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
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.