Docker logging: drivers, rotation, and centralized collection

Choose Docker logging drivers, configure rotation and delivery mode, handle multiline records, and verify container log collection without losing driver compatibility.

Best practices
Illustration of logs flowing through a collection pipeline

Docker logging drivers receive a container process's standard output and standard error, then store or forward those records. They do not automatically collect files written inside the container. That distinction matters when a container disappears: its writable layer is removed with it, while volumes, external storage, and collected logs have separate lifecycles.

For most containerized applications, start with stdout/stderr, choose a driver that your collector supports, and bound local storage. This guide covers driver selection, daemon defaults, per-container overrides, multiline messages, and centralized collection.

Inspect the driver before choosing a collector

docker info --format '{{.LoggingDriver}}'
docker inspect -f '{{.HostConfig.LogConfig.Type}}' web
docker inspect -f '{{.LogPath}}' web

Here web is an existing container name. The first command reports the daemon default; the second reports that container's configuration, which may differ. LogPath depends on the driver. The familiar /var/lib/docker/containers/<id>/<id>-json.log layout is associated with the default rootful Linux data directory and json-file; it is not a universal location, particularly with rootless Docker or Docker Desktop.

Driver What it does Main decision
json-file Stores records in Docker's JSON file format Broad collector compatibility; rotation must be configured
local Stores records in an efficient internal format with rotation and compression Useful when reading through Docker-supported interfaces
syslog / journald Sends records into the selected system logging service Match host logging and retention policies
fluentd, gelf, splunk Sends to a specific logging service Verify connectivity, buffering, and delivery behavior
none Disables driver-managed container logs Use only when another path deliberately supplies the required logs

Docker recommends local for many deployments outside situations that depend on json-file compatibility. Its default limit is five files of 20 MB each, roughly 100 MB of uncompressed log content per container; rotated files are compressed by default. That is a storage bound, not a promise to retain a particular number of hours. Docker manages the internal files, and they should not be treated as a public format for direct tailing. Docker's local driver documentation describes these defaults.

Set a daemon baseline

For a rootful Linux Engine installation, merge the following settings into /etc/docker/daemon.json rather than replacing unrelated daemon configuration:

{
  "log-driver": "local",
  "log-opts": {
    "max-size": "20m",
    "max-file": "5",
    "compress": "true"
  }
}

All log-opts values are strings, including numbers and booleans. On a systemd host, applying a daemon configuration change normally requires restarting Docker:

sudo systemctl restart docker

Plan that restart around your workload. Docker Desktop and rootless installations have different configuration and restart paths. The new defaults apply to newly created containers; existing containers retain their previous settings and must be recreated to change the driver. Restarting an existing container is not enough.

A per-container setting overrides the daemon baseline. For example, given a reachable syslog receiver:

docker run --name web-syslog --log-driver syslog \
  --log-opt syslog-address=tcp://192.0.2.10:514 \
  -d nginx:alpine

Replace the documentation address with your receiver. Plain TCP does not encrypt log contents; use a supported secure transport where required. Driver options are specific to the driver. max-size and max-file do not configure every remote backend's retention.

If a collector requires json-file, retain that driver and explicitly set rotation, for example max-size: "20m" and max-file: "5". The default json-file configuration has no size-based rotation and can consume the host's disk.

Make application records easy to reconstruct

Write operational logs to stdout/stderr where practical: a console transport in Node.js, a configured Python StreamHandler, or a Java console appender. Python's default stream handler writes to stderr; choose stdout explicitly if your policy requires it. File output remains valid for software that needs it, provided a mounted volume, rotation policy, and collector are configured deliberately.

One JSON object per physical line is a useful convention. Encode a stack trace as a string containing escaped newline characters instead of printing each frame as an unrelated record. Multiline text is still possible, but the collector needs an explicit grouping rule and limits; interleaved output from concurrent requests makes reconstruction less dependable. Large messages may also be split by parts of the logging path, so test their handling.

Use timestamps with an explicit offset, preferably UTC, and keep clocks synchronized. The application and host do not need identical display time zones when event times are unambiguous. Mounting /etc/localtime is not a prerequisite for correct logging.

When stdout/stderr is the source, let the driver or host logging service manage its files. Avoid running a second rotation tool against Docker's internal files. If the application intentionally writes its own mounted file, that file still needs a separate rotation policy.

Choose what happens under backpressure

Docker's default delivery mode is blocking: slow log handling can delay the application's writes. The optional non-blocking mode uses a buffer and drops messages when that buffer fills. A larger buffer absorbs a longer burst, but does not create durable delivery.

A local collector can decouple backend availability from an application for a time, subject to the driver's local retention, the collector's queue, disk capacity, and recovery behavior. It is not automatically more reliable than every direct driver. Test an unavailable destination, sustained output, recovery, and host restart using your chosen configuration. Docker documents blocking and non-blocking delivery.

Centralize across hosts with DataKit

Select the collection path before changing drivers. The Guance container integration describes runtime configuration and log collection controls; do not assume that mounting a socket or a directory enables every container and format. Docker socket access is privileged, and a Docker local file cannot be parsed as json-file output.

Use file log collection for intentionally mounted application files, or the documented container path for supported runtime logs. Set and verify service, source, container identity, image, and relevant labels. Kubernetes namespace metadata is meaningful only in a Kubernetes deployment; it is not present on every standalone Docker host.

Parse the application record inside its transport envelope, then map time and severity. Send known success and failure events, including a stack trace, and confirm their fields in Guance before creating error or keyword alerts. An application log containing OOM is one signal; a killed process may leave no final application message, so runtime events and metrics remain useful.

Set retention and archival policies separately from local driver rotation. Local files provide bounded history, while centralized indexing and archive storage have their own configuration and costs. Test recovery after collector or backend downtime to understand how much history survives.

Frequently asked questions

Why is docker logs empty?

First confirm that the application writes to stdout/stderr. Then inspect the driver and its options. json-file, local, and journald support reading logs; remote drivers can also support docker logs through Docker's dual-logging cache. If that cache is disabled, unsupported, or unavailable, the remote backend may be the only place to read them. Dual logging has limits and is not a guaranteed backup of every remotely delivered event.

Is local a drop-in replacement for json-file?

It works with docker logs, but a collector that tails Docker JSON files may need a different configuration or collection method. Recreate a test container, verify ingestion and rotation, then migrate the rest.

What if stack traces are split across records?

Prefer single-line JSON with the stack stored as a field. If that is unavailable, configure the collector's multiline start rule and verify timeouts, size limits, and concurrent output. Do not concatenate unrelated requests simply because the following line lacks a timestamp.

Are files inside containers always lost on restart?

A stopped or restarted container normally retains its writable layer; removal deletes that layer. Volumes and bind mounts persist according to their own lifecycle. Files on those mounts still require collection, capacity management, and rotation.

Further reading

This guide follows the official documentation checked October 14, 2026. Driver and outage scenarios must be validated on your Docker installation; no live Docker daemon was used for these examples.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting