Everything a container writes to stdout and stderr goes to a logging driver. The default driver keeps logs as JSON files without any size limit, which is a classic way for a long-running Docker host to fill its disk. Choosing the right driver and setting rotation takes five minutes, and prevents that.

Reading logs: docker logs.

Check what you use

docker info --format '{{.LoggingDriver}}'
docker inspect -f '{{.HostConfig.LogConfig}}' <container>
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail

The main drivers

Driver Stored docker logs works Notes
json-file (default) /var/lib/docker/containers/<id>/<id>-json.log Yes No rotation unless configured
local Compressed, efficient files Yes Rotates by default (100 MB per container); recommended
journald systemd journal Yes Query with journalctl CONTAINER_NAME=…; journal limits apply
syslog Local or remote syslog No (without dual logging) Central logging
fluentd, gelf, awslogs, loki (plugin) External systems Depends Centralised logging stacks

Since Docker 20.10, dual logging keeps a local cache, so docker logs works even with remote drivers.

Set defaults for all containers (daemon.json)

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

Or keep json-file with rotation:

{
  "log-driver": "json-file",
  "log-opts": { "max-size": "20m", "max-file": "5", "compress": "true" }
}
sudo nano /etc/docker/daemon.json
sudo systemctl restart docker

Defaults apply only to containers created afterwards. Recreate existing ones (docker compose up -d --force-recreate) to pick them up.

Per-service settings in Compose

services:
  app:
    image: myapp:1.8.3
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

See Docker Compose in production.

journald driver

{ "log-driver": "journald" }
journalctl CONTAINER_NAME=web -f
journalctl -u docker --since "1 hour ago"

Logs then follow the journal’s size limits (SystemMaxUse= in journald.conf), and appear alongside system logs. See journalctl.

Emergency: a container log filled the disk

sudo du -sh /var/lib/docker/containers/* | sort -h | tail -5
sudo truncate -s 0 /var/lib/docker/containers/<id>/<id>-json.log    # frees space immediately

Then set rotation, and recreate the container, so it doesn’t happen again. Don’t delete the file while the container is running (the space isn’t freed until it stops). See disk full troubleshooting and Docker disk cleanup.

Central logging

For several servers or many containers, ship logs to one place:

  • Grafana Loki + Promtail/Alloy (or the Loki Docker driver): lightweight, label-based.
  • ELK / OpenSearch with Fluent Bit or Filebeat: powerful search.
  • Hosted services (via fluentd/gelf or agents).

Prefer structured JSON logs from your applications. They’re much easier to filter. See jq.

Good practices

  • Apps should log to stdout/stderr, not files inside the container.
  • Avoid very chatty debug logging in production. It costs disk and CPU.
  • Don’t log secrets (tokens, passwords) — logs are often less protected than databases.

Quick reference

Task Command / setting
Current driver docker info --format '{{.LoggingDriver}}'
Global rotation daemon.json → log-opts max-size, max-file
Recommended driver local
Per service Compose logging:
Free space now truncate -s 0 <id>-json.log
journald journalctl CONTAINER_NAME=x

Related: Docker secrets and Linux log files explained.

  • Docker
  • Logs
  • DevOps