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.
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.
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.
Knowledge check
Why is the checkpoint label safer than changing data-root or networking?
It is harmless, explicitly reloadable, and does not migrate persistent state or alter container connectivity; it isolates configuration-control mechanics from risky host migrations.
What would invalidate the checkpoint’s mutation track immediately?
An existing daemon.json, important workloads, a non-disposable host, or inability to prove that the selected context targets the disposable VM daemon.
Why compare both daemon PID and container PID?
They prove different layers: whether dockerd restarted and whether the application process itself changed.
If HTTP remains healthy but docker info lacks the
new label, did the change succeed?
No. External application continuity and effective daemon policy are separate outcomes; the label must be verified independently.
What discipline from this chapter is essential before Chapter 34 remote API automation?
Precise endpoint/context identity, least privilege, authenticated trust, one policy owner, preserved evidence, and refusal to expose or bypass the daemon control boundary.
Official references and version notes
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.
- Docker Docs — Docker daemon configuration overview — preferred JSON configuration, default paths, flag/JSON conflicts, and Docker Desktop distinction.
-
Docker CLI reference —
dockerd— configuration keys,--validate, proxy flags, registry trust, reloadable options, and multi-daemon cautions. - Docker Docs — Daemon proxy configuration — daemon-side HTTP/HTTPS/NO_PROXY behavior and systemd environment drop-ins.
- Docker Docs — Docker CLI proxy configuration — container/build proxy injection and why it is distinct from daemon egress.
-
Docker Docs — Mirror the Docker Hub library
— pull-through cache configuration, daemon
registry-mirrors, and credential/privacy warnings. - Docker Docs — Live restore — standalone-container continuity, reload, patch-upgrade scope, configuration-change limitations, FIFO log behavior, and Swarm boundary.
- Docker Docs — Read the daemon logs — platform-specific daemon-log locations and incident evidence.
- Docker Docs — Linux post-installation — systemd service enablement and host-integration context.
- Docker Engine 29 release notes — current Engine 29 behavior, validation changes, fixes, and component updates.
- Docker Official Image — registry — current local OCI Distribution image tags used for the optional mirror simulation.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.