Chapter 33Lesson 05~210 minutes

Checkpoint Lab — Daemon Configuration, daemon.json, systemd, Proxies, Registry Mirrors, Live Restore, and Host Integration

Validate and apply one reversible daemon policy change in a disposable Linux VM, prove effective state and container continuity, then roll back with a complete evidence packet.

CheckpointRollbackContinuityEvidence packetChapter 34 bridge

Learning objectives

  • Apply one reversible, reloadable daemon configuration change to a truly disposable Linux VM after offline validation.
  • Predict daemon-process and test-container state before the change, then verify both independently.
  • Capture Engine/CLI/Compose/Buildx/BuildKit/containerd/runc assumptions and service-manager ownership.
  • Preserve daemon logs, effective config, container identity, external health, and rollback evidence in a checkpoint packet.
  • Explain how the same operating discipline prepares for Chapter 34 remote Engine API, TLS, contexts, and automation clients.

1. Checkpoint scenario and allowed environments

The checkpoint changes exactly one daemon policy: a harmless daemon label. It is chosen because Docker currently documents labels as reloadable. The full mutation track must run only in a disposable Linux VM with no important Docker workloads. If you are on Docker Desktop, a shared server, or a host with business containers, complete the validation-only simulation track instead.

Hard guard: never set DCA33_DISPOSABLE_VM=YES unless you own the VM and are willing to discard it. The variable is a learner acknowledgement, not a technical sandbox.

2. Create the evidence directory and preflight

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

date -u +%Y-%m-%dT%H:%M:%SZ | tee "$EVIDENCE/time-before.txt"
docker context show | tee "$EVIDENCE/context.txt"
docker version | tee "$EVIDENCE/docker-version.txt"
docker info | tee "$EVIDENCE/docker-info-before.txt"
docker compose version 2>&1 | tee "$EVIDENCE/compose.txt" || true
docker buildx version 2>&1 | tee "$EVIDENCE/buildx.txt" || true
docker buildx inspect 2>&1 | tee "$EVIDENCE/buildkit-worker.txt" || true
containerd --version 2>&1 | tee "$EVIDENCE/containerd.txt" || true
runc --version 2>&1 | tee "$EVIDENCE/runc.txt" || true

Docker Desktop and some packaged installations may not expose containerd or runc binaries on the client host. Record “not directly exposed” instead of guessing component versions.

3. Capture host/service ownership privately

# Native Linux/systemd only.
systemctl show docker --property=FragmentPath,DropInPaths,MainPID,ActiveEnterTimestamp   | tee "$EVIDENCE/systemd-before.txt"
ps -eo pid,args | grep '[d]ockerd' | tee "$EVIDENCE/dockerd-command.txt"

# Review privately and create a redacted copy if needed:
# sudo systemctl cat docker
# sudo cat /etc/docker/daemon.json

4. Write predictions before mutation

cat > "$EVIDENCE/predictions.md" <<'EOF'
# Predictions
1. Validating the candidate label config will return success without starting a second daemon.
2. systemctl reload docker will keep the same dockerd MainPID and ActiveEnterTimestamp because daemon labels are reloadable.
3. The test container ID/PID/restart count and loopback HTTP health will remain unchanged across the daemon reload.
4. docker info after reload will expose the checkpoint daemon label.
5. Removing the lab daemon.json and reloading will remove that label while preserving the test container.
EOF
cat "$EVIDENCE/predictions.md"

5. Build a validation-only simulation first

cat > "$LAB/proposed-daemon.json" <<'EOF'
{
  "labels": ["devops-academy.chapter=33-checkpoint"]
}
EOF
python -m json.tool "$LAB/proposed-daemon.json" > "$EVIDENCE/proposed-pretty.json"
sudo dockerd --validate --config-file="$LAB/proposed-daemon.json"   | tee "$EVIDENCE/validate-proposed.txt"

If you are not in the disposable VM, stop the checkpoint mutation here. You can still complete the decision/evidence questions using this validated simulation and the current host’s read-only inventory.

6. Disposable-VM guard and collision checks

test "${DCA33_DISPOSABLE_VM:-}" = YES || {
  echo 'Mutation track skipped: not acknowledged as disposable VM.' >&2
  exit 1
}

if sudo test -e /etc/docker/daemon.json; then
  echo 'Existing daemon.json detected; checkpoint refuses to overwrite host policy.' >&2
  exit 1
fi
if docker container inspect dca33-check >/dev/null 2>&1; then
  echo 'Container name collision: dca33-check' >&2
  exit 1
fi

The checkpoint intentionally refuses to merge unknown production policy. This is a small educational change, not a general-purpose config-management script.

7. Start a bounded test service before changing daemon policy

docker pull nginx:1.29.1-alpine
docker image inspect nginx:1.29.1-alpine > "$EVIDENCE/nginx-image-inspect.json"

docker run -d \
  --name dca33-check \
  --label devops-academy.lab=chapter33-checkpoint   -p 127.0.0.1:18081:80   nginx:1.29.1-alpine   | tee "$EVIDENCE/container-id-create.txt"

curl -fsS http://127.0.0.1:18081/ > "$EVIDENCE/http-before.html"
docker inspect -f 'id={{.Id}} pid={{.State.Pid}} restart={{.RestartCount}} status={{.State.Status}}' dca33-check   | tee "$EVIDENCE/container-before.txt"
systemctl show docker --property=MainPID,ActiveEnterTimestamp   | tee "$EVIDENCE/daemon-before-reload.txt"

8. Apply the validated reversible label policy

sudo install -o root -g root -m 0644   "$LAB/proposed-daemon.json" /etc/docker/daemon.json

# Re-validate the exact installed path before reload.
sudo dockerd --validate --config-file=/etc/docker/daemon.json   | tee "$EVIDENCE/validate-installed.txt"

RELOAD_START=$(date -u +%Y-%m-%dT%H:%M:%SZ)
sudo systemctl reload docker
printf '%s
' "$RELOAD_START" | tee "$EVIDENCE/reload-start.txt"

The change is deliberately reloadable. A restart would add unnecessary state transition and would not test the chapter’s reload reasoning.

9. Verify daemon and container predictions independently

date -u +%Y-%m-%dT%H:%M:%SZ | tee "$EVIDENCE/time-after-reload.txt"
systemctl show docker --property=MainPID,ActiveEnterTimestamp   | tee "$EVIDENCE/daemon-after-reload.txt"
docker info | tee "$EVIDENCE/docker-info-after-reload.txt"
docker inspect -f 'id={{.Id}} pid={{.State.Pid}} restart={{.RestartCount}} status={{.State.Status}}' dca33-check   | tee "$EVIDENCE/container-after-reload.txt"
curl -fsS http://127.0.0.1:18081/ > "$EVIDENCE/http-after-reload.html"

sudo journalctl -u docker --since "$RELOAD_START" --no-pager   > "$EVIDENCE/daemon-journal-after-reload.txt"

Compare the daemon PID/start timestamp, the container identity/PID/restart count, the external HTTP response, daemon logs, and the effective label. No single signal is sufficient by itself.

10. Roll back to the exact initial configuration state

sudo rm /etc/docker/daemon.json
ROLLBACK_START=$(date -u +%Y-%m-%dT%H:%M:%SZ)
sudo systemctl reload docker
printf '%s
' "$ROLLBACK_START" | tee "$EVIDENCE/rollback-start.txt"

systemctl show docker --property=MainPID,ActiveEnterTimestamp   | tee "$EVIDENCE/daemon-after-rollback.txt"
docker info | tee "$EVIDENCE/docker-info-after-rollback.txt"
docker inspect -f 'id={{.Id}} pid={{.State.Pid}} restart={{.RestartCount}} status={{.State.Status}}' dca33-check   | tee "$EVIDENCE/container-after-rollback.txt"
curl -fsS http://127.0.0.1:18081/ > "$EVIDENCE/http-after-rollback.html"

Because the VM started without a daemon configuration file, removing the lab file is an exact rollback. The label should disappear while the daemon and test service remain healthy.

11. Verify continuity with explicit comparisons

diff -u "$EVIDENCE/container-before.txt" "$EVIDENCE/container-after-reload.txt"
diff -u "$EVIDENCE/container-before.txt" "$EVIDENCE/container-after-rollback.txt"
diff -u "$EVIDENCE/http-before.html" "$EVIDENCE/http-after-reload.html"
diff -u "$EVIDENCE/http-before.html" "$EVIDENCE/http-after-rollback.html"

Unexpected differences are first-failure evidence. Do not delete them. Explain whether the difference is harmless formatting/content timestamp drift or a violated continuity prediction.

12. Evidence packet manifest

Evidence family Required checkpoint contents
Environment UTC timestamps, context, Engine/CLI, Compose, Buildx/BuildKit, containerd/runc availability
Configuration ownership systemd fragment/drop-in paths, dockerd command line, statement that original daemon.json was absent
Validation generic JSON parse, dockerd --validate candidate and installed-path results
Daemon lifecycle MainPID + ActiveEnterTimestamp before/reload/rollback, journal windows
Container continuity container ID/PID/restart count/status before/reload/rollback
External health loopback HTTP response before/reload/rollback
Effective policy docker info before/after showing label appearance and disappearance
Security no real proxy secrets, no insecure registry, no remote API exposure, no socket sharing
Rollback exact removal of lab-owned config and final healthy state
Limitations disposable VM scope; reloadable label does not model restart-required migrations

13. Clean up the disposable application object

docker rm -f dca33-check

date -u +%Y-%m-%dT%H:%M:%SZ | tee "$EVIDENCE/time-final.txt"
docker ps -a --filter label=devops-academy.lab=chapter33-checkpoint   | tee "$EVIDENCE/lab-containers-final.txt"

The evidence directory remains. No global prune, daemon storage deletion, registry trust weakening, or unrelated container removal is used.

14. What this chapter adds to a production Docker operating model

Chapter 33 turns daemon configuration into a controlled host-policy lifecycle: one owner per setting; current-version validation; explicit service-manager and secret boundaries; separate daemon/container proxy paths; trusted registry/mirror policy; reload/restart classification; continuity evidence; daemon-log preservation; and exact rollback.

Chapter 34

Docker Engine API, SDKs, Remote Daemons, TLS Authentication, Contexts, and Automation Clients

The daemon is now treated as a governed control plane. Next, you will cross the process boundary intentionally: Engine API versioning, local versus remote sockets, TLS client/server authentication, contexts, SDKs, and automation clients without turning the Docker API into an unauthenticated host-control endpoint.

Knowledge check

Why is the checkpoint label safer than changing data-root or networking?

What would invalidate the checkpoint’s mutation track immediately?

Why compare both daemon PID and container PID?

If HTTP remains healthy but docker info lacks the new label, did the change succeed?

What discipline from this chapter is essential before Chapter 34 remote API automation?

Official references and version notes

Checkpoint baseline date:

2026-09-22. The mutation track intentionally exercises a currently reloadable daemon label only inside a disposable Linux VM. Learners on Docker Desktop or shared hosts use the validation-only path and do not translate native-systemd commands blindly.

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.