Logs, Logging Drivers, Rotation, stdout/stderr Contracts, Events, stats, and Container Observability: Configuration, Design Choices, and Tradeoffs
Choose Docker logging drivers, delivery modes, correlation metadata, and retention ownership using explicit reliability, security, and operations tradeoffs.
Learning objectives
-
Choose among
local,json-file, and remote drivers based on retention, backpressure, availability, and operations. - Compare blocking and non-blocking log delivery, including the deliberate message-loss tradeoff.
- Keep application logging on stdout/stderr while using labels/tags for correlation instead of hiding critical logs in writable layers.
- Place retention ownership deliberately at the daemon or external logging platform and document the evidence path.
1. Start with the operating contract
Before choosing a driver, answer four questions: How much output can the application produce? Must the application ever block on logging? How long must evidence survive locally and remotely? What is the acceptable data-loss mode if the sink or disk fails? Those answers drive the configuration.
2. local versus json-file
The daemon default remains json-file for compatibility.
Without max-size/max-file, it does not
rotate and can consume substantial disk. Docker recommends the
local driver for general use because it rotates and
compresses by default. The current documented
local defaults are five files with a 20 MB maximum
each, before compression—about 100 MB per container.
| Choice | Strength | Risk / prerequisite | Best evidence |
|---|---|---|---|
local |
Efficient local storage, rotation/compression by default,
docker logs.
|
Retention is finite and local to daemon host. |
Driver/options plus bounded docker logs; daemon
disk capacity.
|
json-file |
Simple JSON records and broad compatibility. | No rotation by default; direct file access remains unsupported. |
Explicit rotation options; disk trend;
docker logs.
|
| Remote driver | Central retention/search outside the host. | Network/auth/backpressure failure domain; provider-specific semantics. | Remote receipt plus driver/daemon delivery evidence and local-cache policy. |
3. Blocking versus non-blocking delivery
Docker’s default log-delivery mode is blocking: application output
is delivered directly to the driver. If the driver or destination
blocks, application writes can block. Non-blocking mode inserts a
per-container buffer; current Docker documentation gives a default
max-buffer-size of 1 MB. When that buffer is full, new
messages are dropped.
This is not a performance toggle with no downside. Blocking favors log preservation but can couple application progress to the logging path. Non-blocking favors application availability but explicitly accepts message loss under sustained backpressure. Document which outcome is safer for the workload.
# Example policy only; run on a disposable container if testing.
docker run --rm --log-driver local --log-opt mode=non-blocking --log-opt max-buffer-size=4m alpine:3.22 echo 'synthetic telemetry'
4. Remote drivers and the dual-logging boundary
Modern Docker Engine automatically enables a local dual-logging
cache when a configured remote logging driver cannot itself read
logs. This normally keeps recent output available through
docker logs. If that cache is disabled,
docker logs may fail for a remote driver that cannot
read back data. The external sink remains the authoritative proof of
remote delivery.
Current defaults for the dual-log cache mirror local:
up to five 20 MB files before compression. Network problems to a
remote driver can also prevent cache writes in some failure paths;
do not assume “remote failed but local always has everything.”
5. Application file versus stdout contract
A log file written only into the container writable layer has poor lifecycle semantics: replacement can discard it, a stopped/dead container can make retrieval awkward, and backup/rotation become application-specific. Prefer stdout/stderr for operational events unless the application has a strong file-based contract that is deliberately mounted, rotated, and collected.
Do not bind-mount arbitrary host log directories merely to imitate a VM. That increases host coupling and permissions complexity. If a required file log exists, treat its volume/mount and collection path as explicit persistent/external state.
6. Labels and tags for correlation—not secrets
Some logging drivers can add selected container labels or
environment values to log records. Engine 29.5 also added custom
attribute support to the local driver. This can improve
correlation for fields such as service, environment, release, or
project. Never use secret-bearing environment variables as log
metadata.
docker run --rm --label app=payments-demo --label release=2026-09-lab --log-driver local --log-opt labels=app,release alpine:3.22 echo 'event=ready'
7. Decide who owns retention
Daemon-side rotation protects host disk and gives short troubleshooting history. External retention supports longer search, compliance, and cross-host correlation. These are complementary. Define maximum local bytes/container, expected volume/day, external retention duration, and failure behavior when either tier is unavailable.
Retention is also a privacy/security control: shorter retention can reduce exposure, while longer retention can be mandatory for audit. The correct answer is workload-specific.
8. Platform and daemon-log differences
On Linux with systemd, daemon logs are commonly read through
journald. Docker Desktop runs Engine components inside its VM and
documents platform-specific init.log locations. Windows
containers use Windows Event Log. A runbook that hard-codes
/var/log/docker.log is not portable evidence.
9. Worked decision table
| Scenario | Recommended direction | Prerequisites / trust | Evidence to verify |
|---|---|---|---|
| Developer laptop, moderate logs | Per-container or daemon local. |
Finite local retention acceptable. |
Driver/options, disk headroom, docker logs.
|
| Compatibility-sensitive tooling expects JSON driver |
json-file with explicit
max-size/max-file.
|
Rotation tested; disk monitoring exists. | Inspect log options plus disk/rotation observations. |
| Central production search | Reviewed remote driver/agent plus documented local cache policy. | TLS/auth, sink availability, retention, data sensitivity. | Remote receipt timestamp/identity + daemon driver state. |
| Bursty app must not block | Non-blocking delivery with measured buffer and loss acceptance. | Stakeholders accept dropped logs under saturation. | Buffer settings plus synthetic backpressure test and drop detection. |
Knowledge check
Why can local be safer for host disk than default json-file?
local rotates and compresses by default; json-file does not rotate unless max-size/max-file are configured.
What is the central tradeoff of non-blocking delivery?
It reduces application backpressure but can drop new messages after the buffer fills.
Does docker logs prove a remote logging system received a record?
No. With dual logging it can prove recent local cache availability; remote receipt must be verified at the external sink.
Why avoid secrets in labels or env-selected log attributes?
Those values can be copied into logs/metadata and retained or transmitted to external systems.
Who should own long-term retention?
Whichever deliberately designed tier meets the workload’s compliance, durability, cost, sensitivity, and retrieval requirements; local Docker rotation alone is usually short-term host protection.
Official references and version notes
- Docker Docs — Configure logging drivers — daemon/container driver selection, delivery modes, labels/tags, and current default-driver behavior.
- Docker Docs — Local file logging driver — default rotation/compression behavior and supported options.
- Docker Docs — JSON file logging driver — JSON framing and explicit rotation options.
-
Docker Docs — Dual logging
— how
docker logscan remain available with remote drivers and when it does not. -
Docker CLI — docker container logs
— timestamps,
--since,--until, follow, and tail behavior. - Docker CLI — docker system events — event scope, filters, JSON Lines formatting, and bounded event history.
- Docker CLI — docker container stats — CPU, memory, network, block I/O, PIDs, and Linux cache-reporting notes.
- Docker Docs — Read daemon logs — platform-specific locations and systemd/desktop guidance.
- Docker Engine 29 release notes — current Engine baseline and logging-related fixes/features.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.