Stop Docker Logs from Filling Your Disk
14 Nov 2025Docker’s default logging driver keeps every line a container ever writes to stdout, forever, in a single JSON file, with no size limit. A chatty app running for a few months can quietly fill a disk with nothing but its own logs. Fix the daemon config once, before it happens, not after you’re doing disk triage at 2am.
Where the logs actually live
Every container’s stdout/stderr goes to a JSON file under:
/var/lib/docker/containers/<container-id>/<container-id>-json.log
Check the current damage:
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -rh | head -10
It’s not unusual to find one container’s log file alone in the multi-gigabyte range if it’s been running a while with a retry loop or verbose request logging and no rotation configured.
1. Set a daemon-wide default
This is the fix that matters most, because it applies to every container going forward without touching individual Compose files. Edit (or create) /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
max-size caps each log file at 10MB before it rotates; max-file keeps 3 of them (so ~30MB max per container, total, across current plus rotated files). Restart Docker for it to take effect:
sudo systemctl restart docker
Restarting the Docker daemon restarts every container on the host — plan this for a maintenance window, not mid-traffic.
2. Existing containers won’t pick this up automatically
The daemon-wide config only applies to containers created after the change. Containers already running keep whatever logging config they started with. You need to recreate them:
docker compose up -d --force-recreate
Or, per container: docker stop <name> && docker rm <name> then start it again from your Compose file or run command. This is the step people miss — they set daemon.json, restart Docker, and are confused a week later when the same container’s log file is still growing unbounded.
3. Override per-service when you need to
If one service is unusually chatty and you want a bigger allowance, or another is critical and you want more retained history, override in Compose:
services:
app:
logging:
driver: json-file
options:
max-size: "20m"
max-file: "5"
Compose-level logging config overrides the daemon default for that service only.
4. Consider whether you need json-file at all
If you’re shipping logs somewhere external — a log aggregator, Loki, even just journald — you can point Docker at a different driver and stop keeping large local files entirely:
logging:
driver: local
options:
max-size: "10m"
max-file: "3"
The local driver is Docker’s more efficient alternative to json-file — smaller on-disk footprint for the same log volume, using a more compact binary format. It’s a reasonable default for new setups where you don’t specifically need raw JSON log files on disk.
What rotation doesn’t fix
Log rotation caps Docker’s container logs. It does nothing for application-level log files written inside the container to its own filesystem (a Rails app writing to log/production.log, for instance) — those need their own rotation, typically logrotate inside the image or writing to stdout instead so Docker’s own rotation covers them. The cleanest fix for most apps: log to stdout/stderr only, and let Docker’s logging driver be the single place rotation is configured, rather than managing rotation in two places.
The takeaway
Set max-size and max-file in daemon.json before you have a problem — it’s a five-minute change. If you’re reading this because a disk is already full, check /var/lib/docker/containers/*/*-json.log first; it’s one of the most common causes and the fix (truncate the file, or docker compose restart the container) is safe and immediate.