Chapter 23Lesson 04~120 minutes

Logs, Logging Drivers, Rotation, stdout/stderr Contracts, Events, stats, and Container Observability: Diagnostics, Failure Modes, Security, and Performance

Diagnose Docker log growth, missing remote delivery, writable-layer logs, secret leakage, stale driver configuration, and backpressure from preserved evidence.

Container observabilityLogging driversEvents & statsRotation & retentionEvidence-first

Learning objectives

  • Diagnose disk growth, missing logs, dropped remote delivery, secret leakage, and stale logging configuration from first-failure evidence.
  • Distinguish application silence from driver/sink failure, daemon failure, and container/process lifecycle events.
  • Explain why changing the daemon default does not retrofit existing containers.
  • Apply the smallest safe correction without destructive cleanup, blanket daemon changes, or exposure of secrets.
Incident rule. Preserve first-failure evidence before changing a logging driver, recreating a container, deleting files, restarting the daemon, or widening access. A telemetry failure can erase the very evidence needed to diagnose it.

1. Evidence-first diagnostic sequence

  1. Record context, Engine/CLI versions, host/Desktop boundary, and time.
  2. Record container ID/name, exact image identity, state, exit code/OOM flag, and logging driver/options.
  3. Capture a bounded application-log window and Engine events before history rolls over.
  4. Capture a stats sample if the container is still running; preserve resource configuration if it has exited.
  5. Inspect daemon logs for driver, filesystem, transport, or Engine errors.
  6. For remote logging, prove external sink receipt independently without exposing credentials.
  7. Apply one least-destructive correction and rerun the smallest reproduction.
docker context show
docker version
docker inspect dkr23-app --format '{{json .State}} {{json .HostConfig.LogConfig}}'
docker logs --timestamps --since 10m --tail 500 dkr23-app 2>&1
docker events --since 10m --filter container=dkr23-app --format '{{json .}}'
docker stats --no-stream --format '{{json .}}' dkr23-app 2>/dev/null || true

2. Failure: unbounded json-file growth

Symptom: daemon-host disk pressure rises while application behavior is otherwise normal. Cause: high-volume json-file containers with no rotation can accumulate data indefinitely until external capacity limits intervene.

Preserve: exact container driver/options, host disk usage trend, daemon warnings, container output rate, and retention requirements. Correction: for future/recreated containers, choose local or configure explicit json-file rotation. Do not delete Docker-managed log files by hand.

3. Failure: critical logs exist only inside the writable layer

If the application writes only /app/logs/app.log and the container is replaced, operational evidence can disappear with its writable layer. The correction is not “docker cp the file every incident.” Establish stdout/stderr or an explicit persistent/collector contract, then rebuild/redeploy.

4. Failure: a fake credential leaks into logs

Use a synthetic value to understand the response without exposing a real secret. Once a real secret reaches logs, rotation does not guarantee immediate removal from every retained local/remote copy. Treat it as a credential incident according to the relevant secret-rotation and retention procedures.

docker rm -f dkr23-badlog 2>/dev/null || true
docker run --name dkr23-badlog --label academy=docker-ch23 alpine:3.22   sh -c 'echo "ERROR demo_auth=FAKE-ONLY-NOT-A-CREDENTIAL" >&2; exit 23' || true

docker logs --timestamps dkr23-badlog 2>&1 | tee dkr23-evidence/badlog-original.txt
docker inspect dkr23-badlog --format 'exit={{.State.ExitCode}} image={{.Image}} log={{json .HostConfig.LogConfig}}'
Repair the application contract. Redact sensitive values before emission. For a real exposure, rotate/revoke the credential and follow retention/redaction procedures at every sink. Do not “fix” the evidence by deleting broad log storage.

5. Failure: docker logs and the remote sink disagree

With a remote driver, docker logs can be served by dual logging rather than by reading back from the remote system. Therefore these states are possible: local recent logs exist but remote delivery failed; remote logs exist but local cache was disabled/rotated; both are missing because delivery/cache failed; or the application emitted nothing.

Inspect the per-container driver/options, daemon logs, network/TLS/provider errors, dual-cache configuration, and remote receipt. Do not equate a successful docker logs command with successful external transport.

6. Failure: changing the daemon default does not fix existing containers

Docker documentation explicitly states that daemon logging changes apply to newly created containers. Existing containers retain the logging configuration they were created with. A restart of the existing container does not replace its HostConfig.LogConfig.

# Read-only proof for two containers created at different times.
docker inspect OLD NEW --format '{{.Name}} {{json .HostConfig.LogConfig}}'

7. Failure: tuning without disk or latency evidence

Increasing buffers, retention, or remote retries can move pressure elsewhere. Larger local retention consumes disk; non-blocking buffers consume memory and can still drop; blocking delivery can stall the application; aggressive remote retry can amplify incidents. Measure output rate, disk headroom, sink latency/error rate, and application tolerance first.

8. Causal map: do not troubleshoot the wrong layer

Symptom Likely evidence plane Do not jump to
No app logs, container never started Engine events / inspect / daemon logs Remote sink tuning.
App emits, local logs exist, remote missing Driver transport / daemon / external sink Application restart first.
Disk fills on daemon host File driver retention + host storage Deleting arbitrary files in Docker data root.
Container latency rises during log outage Blocking driver/backpressure path CPU limits without evidence.
docker logs unavailable with remote driver Dual-log/read capability/config Assuming application emitted nothing.
Stats show rising PIDs but logs normal Runtime/resource plane Changing logging driver.

Knowledge check

Why should you not delete json-file/local driver files manually during disk pressure?

You changed daemon.json log-driver and restarted Docker, but an old container still uses json-file. Bug?

docker logs shows a line but the remote SIEM has none. What does that prove?

Why is a real secret in logs more serious than one file on disk?

A high-volume app stalls when the remote logger is slow. Which design axis matters?

Next lesson

Next: Checkpoint Lab — Logs, Logging Drivers, Rotation, stdout/stderr Contracts, Events, stats, and Container Observability

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

Official references and version notes

Version baseline, verified 2026-09-21.

Docker Engine 29.8.1 is the current Engine baseline used for compatibility notes. The daemon default logging driver remains json-file; Docker recommends local for general use because it rotates by default. The mandatory labs configure logging per container so they do not require editing daemon.json or restarting Docker. Always record docker version, docker info, context, the actual per-container HostConfig.LogConfig, and platform-specific daemon-log location instead of assuming defaults.

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.