Chapter 33Lesson 02~195 minutes

Daemon Configuration, daemon.json, systemd, Proxies, Registry Mirrors, Live Restore, and Host Integration: Guided Hands-On Workflow and Core Operations

Inspect effective daemon ownership, validate proposed configuration offline, model systemd drop-ins and mirrors, and apply a reversible harmless setting only inside an explicitly disposable Linux daemon environment.

ValidationDrop-insProxyRegistry mirrorDisposable lab

Learning objectives

  • Create a safe evidence packet for daemon ownership before changing configuration.
  • Validate correct and intentionally broken candidate JSON files without restarting the current daemon.
  • Model systemd drop-ins and daemon proxy ownership without storing real credentials.
  • Run a local OCI Distribution proxy-cache simulation and distinguish “mirror service exists” from “daemon is configured to use it.”
  • Apply a harmless reloadable daemon label and test live-restore behavior only inside an explicitly disposable Linux VM; provide a no-admin simulation path elsewhere.

1. Two-track lab design

Track A (mandatory everywhere) is read-only/offline: inventory the current Engine, validate temporary configuration files, generate a systemd drop-in model, and run a local mirror service without pointing the production daemon at it. It does not restart or reload Docker.

Track B (optional but fully runnable) is for a fresh disposable Linux VM you control. It applies one harmless reloadable daemon label, optionally points the disposable daemon at the local mirror, and demonstrates live restore. Do not use Track B on a workstation hosting important containers.

Precondition for Track B: this must be a disposable VM with no business workloads and a rollback path. If that statement is false, stop after Track A.

2. Capture environment and component assumptions

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

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

Record actual installed versions rather than assuming that Engine packages, Docker Desktop, static binaries, and distro packaging bundle the same component builds.

3. Read-only service ownership on native Linux

# Run only if the selected Docker daemon is this Linux host.
systemctl show docker --property=FragmentPath,DropInPaths,MainPID,ActiveEnterTimestamp   | tee "$EVIDENCE/systemd-owner.txt"
ps -eo pid,args | grep '[d]ockerd' | tee "$EVIDENCE/dockerd-command.txt"

# Inspect privately; do NOT tee raw output if it may contain credentials:
# sudo systemctl cat docker
# sudo cat /etc/docker/daemon.json

If docker context show points elsewhere, these systemd commands are client-host evidence and must not be mislabelled as remote-daemon evidence.

4. Offline validation: one good file and one broken file

cat > "$LAB/good-daemon.json" <<'EOF'
{
  "labels": ["devops-academy.chapter=33-lab"]
}
EOF

cat > "$LAB/bad-daemon.json" <<'EOF'
{
  "labels": ["devops-academy.chapter=33-lab"],
  "definitely-not-a-dockerd-option": true
}
EOF

sudo dockerd --validate --config-file="$LAB/good-daemon.json"   | tee "$EVIDENCE/validate-good.txt"

set +e
sudo dockerd --validate --config-file="$LAB/bad-daemon.json"   >"$EVIDENCE/validate-bad.txt" 2>&1
BAD_RC=$?
set -e
printf 'bad validation rc=%s
' "$BAD_RC" | tee -a "$EVIDENCE/validate-bad.txt"
test "$BAD_RC" -ne 0

The failed candidate remains as evidence. The repair is not “restart and see”; it is to correct the unsupported directive, revalidate, and only then consider rollout.

5. Model a systemd proxy drop-in with fake values

mkdir -p "$LAB/systemd-model"
cat > "$LAB/systemd-model/http-proxy.conf" <<'EOF'
[Service]
Environment="HTTP_PROXY=http://proxy.example.test:3128"
Environment="HTTPS_PROXY=http://proxy.example.test:3128"
Environment="NO_PROXY=localhost,127.0.0.1,.example.test"
EOF
cat "$LAB/systemd-model/http-proxy.conf"

This is a model file only. It is not installed under /etc/systemd/system. Real proxy URLs can contain credentials; never commit or publish those values casually.

6. Compare daemon proxy and container/build proxy

Need Correct owner Typical persistent location Verification
Daemon pulls/pushes through proxy dockerd daemon proxy fields or service environment daemon logs + successful pull/push
New containers receive proxy env Docker CLI config / explicit container env ~/.docker/config.json or Compose/service config docker inspect / controlled env output
Build step reaches proxy BuildKit build args/env or network policy CLI config/build configuration plain build log + dependency fetch evidence
Application runtime proxy application/container configuration Compose/runtime config or secret-aware mechanism application request evidence

7. Start a local pull-through-cache simulation

# Guard against name collision.
if docker container inspect dca33-mirror >/dev/null 2>&1; then
  echo 'Refusing to reuse preexisting dca33-mirror' >&2; exit 1
fi

docker pull registry:3.1.1
docker image inspect registry:3.1.1 > "$EVIDENCE/registry-image-inspect.json"

docker run -d \
  --name dca33-mirror \
  --label devops-academy.lab=chapter33   -p 127.0.0.1:5001:5000   -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io   registry:3.1.1   | tee "$EVIDENCE/mirror-container-id.txt"

curl -fsS http://127.0.0.1:5001/v2/ | tee "$EVIDENCE/mirror-v2.txt"
docker logs dca33-mirror > "$EVIDENCE/mirror-logs.txt" 2>&1

This proves that a local Distribution service is reachable and configured in proxy mode. It does not prove the Docker daemon is using it as a mirror. Daemon use requires a registry-mirrors policy change, which Track A intentionally does not apply.

8. Validate a mirror configuration without applying it

cat > "$LAB/mirror-daemon.json" <<'EOF'
{
  "registry-mirrors": ["http://127.0.0.1:5001"],
  "labels": ["devops-academy.chapter=33-lab"]
}
EOF
sudo dockerd --validate --config-file="$LAB/mirror-daemon.json"   | tee "$EVIDENCE/validate-mirror.txt"

Loopback is used only for the local disposable simulation. Production mirrors should use authenticated/trusted TLS appropriate to your environment. The lesson does not add a broad insecure-registry rule.

9. Track B: preflight the disposable Linux VM before daemon mutation

# OPTIONAL: disposable Linux VM only.
test "${DCA33_DISPOSABLE_VM:-}" = YES || {
  echo 'Set DCA33_DISPOSABLE_VM=YES only inside the disposable VM.' >&2
  exit 1
}

docker ps -a --format '{{.Names}}' | tee "$EVIDENCE/vm-containers-before.txt"

# This teaching track expects no preexisting daemon.json.
if sudo test -e /etc/docker/daemon.json; then
  echo 'Existing daemon.json detected. Use Track A instead of overwriting it.' >&2
  exit 1
fi

systemctl show docker --property=MainPID,ActiveEnterTimestamp   | tee "$EVIDENCE/daemon-before.txt"

Refusing to overwrite an existing configuration is deliberate. A real configuration-management rollout would merge versioned policy; this small lab uses a fresh VM to keep rollback exact.

10. Track B: apply one harmless reloadable daemon label

cat > /tmp/dca33-daemon.json <<'EOF'
{
  "labels": ["devops-academy.chapter=33-checkpoint"]
}
EOF
sudo dockerd --validate --config-file=/tmp/dca33-daemon.json   | tee "$EVIDENCE/vm-validate.txt"
sudo install -o root -g root -m 0644 /tmp/dca33-daemon.json /etc/docker/daemon.json
sudo systemctl reload docker

systemctl show docker --property=MainPID,ActiveEnterTimestamp   | tee "$EVIDENCE/daemon-after-reload.txt"
docker info | tee "$EVIDENCE/docker-info-after-reload.txt"

Daemon labels are currently reloadable. The expected observation is that the daemon PID/start timestamp stays stable while the effective label appears in docker info.

11. Track B: optional mirror-use verification

# OPTIONAL in the disposable VM: replace daemon.json with the validated mirror+label model.
sudo install -o root -g root -m 0644 "$LAB/mirror-daemon.json" /etc/docker/daemon.json
sudo systemctl reload docker

docker pull busybox:1.37.0
docker image inspect busybox:1.37.0 > "$EVIDENCE/busybox-inspect.json"
docker logs dca33-mirror > "$EVIDENCE/mirror-logs-after-pull.txt" 2>&1

Evidence is the combination of daemon configuration, successful pull, and mirror logs showing the request path. A successful pull alone cannot prove which upstream path was used.

12. Track B: live-restore semantics, only in the disposable VM

# Replace config with live-restore + lab label; validate first.
cat > /tmp/dca33-live.json <<'EOF'
{
  "live-restore": true,
  "labels": ["devops-academy.chapter=33-checkpoint"]
}
EOF
sudo dockerd --validate --config-file=/tmp/dca33-live.json
sudo install -o root -g root -m 0644 /tmp/dca33-live.json /etc/docker/daemon.json
sudo systemctl reload docker

if docker container inspect dca33-live >/dev/null 2>&1; then
  echo 'Refusing to reuse preexisting dca33-live' >&2; exit 1
fi

docker run -d --name dca33-live   --label devops-academy.lab=chapter33   -p 127.0.0.1:18080:80   nginx:1.29.1-alpine
curl -fsS http://127.0.0.1:18080/ > "$EVIDENCE/http-before-daemon-stop.html"

docker inspect -f 'id={{.Id}} pid={{.State.Pid}} restart={{.RestartCount}}' dca33-live   | tee "$EVIDENCE/live-before.txt"

sudo systemctl stop docker
curl -fsS http://127.0.0.1:18080/ > "$EVIDENCE/http-while-daemon-down.html"
sudo systemctl start docker

docker inspect -f 'id={{.Id}} pid={{.State.Pid}} restart={{.RestartCount}}' dca33-live   | tee "$EVIDENCE/live-after.txt"

This is intentionally disruptive to the disposable VM daemon and therefore never belongs on a shared host as a training shortcut. The HTTP request is external evidence that the container process kept serving while dockerd was unavailable.

13. Cleanup and rollback

docker rm -f dca33-live 2>/dev/null || true
docker rm -f dca33-mirror 2>/dev/null || true

# Disposable VM Track B only: return to the original “no daemon.json” state.
if [ "${DCA33_DISPOSABLE_VM:-}" = YES ]; then
  sudo rm -f /etc/docker/daemon.json
  sudo systemctl reload docker || sudo systemctl restart docker
  systemctl show docker --property=MainPID,ActiveEnterTimestamp     | tee "$EVIDENCE/daemon-after-rollback.txt"
fi

The fallback restart is allowed only in the disposable VM because removing a configuration key that is not reloadable may require restart. On any non-disposable host, use the organization’s normal change/rollback procedure instead.

14. Small challenge: choose the layer before the command

Your organization reports: “containers can reach the corporate proxy, but docker pull cannot.” Before changing anything, identify the owner and evidence. The correct hypothesis is daemon egress, not container environment. Capture daemon proxy policy, endpoint identity, and daemon logs; do not add proxy variables to the application as a random retry.

Knowledge check

Why is a running local registry proxy container not proof that Docker is using it as a mirror?

What makes the harmless daemon-label change suitable for a reload exercise?

Why does Track B refuse an existing /etc/docker/daemon.json?

What evidence proves live restore rather than an automatic container restart?

Where should real proxy credentials be recorded in the evidence packet?

Next lesson

Next: Daemon Configuration, daemon.json, systemd, Proxies, Registry Mirrors, Live Restore, and Host Integration: Configuration, Design Choices, and Tradeoffs

Continue with the next lesson in the course sequence and carry forward the evidence-first Docker operating model.

Official references and version notes

Lab baseline date: 2026-09-22. The optional mirror simulation uses Docker Official Image registry:3.1.1, the current stable v3 line at verification time; the lab records the pulled image inspection/digest so evidence remains immutable even if tags later move.

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.