Stop Docker Logs From Filling the Disk on a Django Host
Stop Docker container logs from filling the disk on a Django server: find the large json.log files, set max-size and max-file in daemon.json or Compose, use the local driver, and reduce noisy logging.
Problem statement
The server's disk reached 100%, PostgreSQL stopped accepting writes, and the culprit is under /var/lib/docker/containers/:
$ sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail -3
2.1G /var/lib/docker/containers/4f1c.../4f1c...-json.log
9.8G /var/lib/docker/containers/a7e2.../a7e2...-json.log
31G /var/lib/docker/containers/c03d.../c03d...-json.log
Docker's default json-file logging driver keeps everything a container writes to stdout and stderr, forever, in one growing file per container. A Django app logging every request, a Celery worker at DEBUG level, or a crash loop printing tracebacks can fill a disk in days. Docker does not rotate these logs unless you tell it to.
- Find the biggest files:
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail. - Free space now:
sudo truncate -s 0 <file>(do notrma file Docker holds open). - Set rotation globally in
/etc/docker/daemon.json:"log-opts": {"max-size": "20m", "max-file": "5"}. - Restart Docker, then recreate containers; existing containers keep their old settings.
- Reduce volume at the source: log level
INFO, no per-request noise from health checks.
Step-by-step solution
1. Identify which container
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail -5
docker ps -a --no-trunc --format '{{.ID}} {{.Names}}' | grep c03d
Map the directory ID back to a container name. Check what it logs: docker logs --tail 50 <name>.
2. Free space safely
sudo truncate -s 0 /var/lib/docker/containers/c03d.../c03d...-json.log
df -h /
truncate empties the file while Docker keeps writing to it. Deleting it with rm leaves the space allocated until the container stops, because the daemon still has the file open.
3. Configure rotation for every container
{
"log-driver": "local",
"log-opts": {
"max-size": "20m",
"max-file": "5"
}
}
Save as /etc/docker/daemon.json, then:
sudo systemctl restart docker
docker compose up -d --force-recreate
The local driver stores logs in a compressed, rotated format and still works with docker logs. If you prefer json-file (some log shippers read those files directly), keep "log-driver": "json-file" with the same log-opts. Either way, each container is capped at about 100 MB here.
Daemon defaults apply only to containers created after the restart. Existing containers keep the configuration they were created with until recreated.
4. Or set it per service in Compose
x-logging: &default-logging
driver: local
options:
max-size: "20m"
max-file: "5"
services:
web:
logging: *default-logging
worker:
logging: *default-logging
Per-service settings travel with the project, which helps on servers where you do not control daemon.json.
5. Log less at the source
Rotation caps disk use; reducing noise makes the remaining logs useful:
- Run Django and Celery at
INFO, notDEBUG, in production. - Exclude health checks from Gunicorn access logs or the proxy's logs; a check every 5 seconds from three sources is 50,000 lines a day.
- Fix crash loops instead of letting them print the same traceback every second.
- Ship logs to a central system (Loki, CloudWatch, Datadog) if you need retention beyond the local cap.
Verification check:
docker inspect --format '{{.HostConfig.LogConfig}}' $(docker ps -q)
Every running container should show your driver and options. Check df -h and the log directory sizes again after a week.
Explanation
Containers are expected to log to stdout and stderr, and Docker captures those streams through a logging driver. The default json-file driver writes each line as a JSON object to a file per container, with no size limit unless max-size is set. That default exists for compatibility, but it means a long-running container's log only ever grows. Docker removes the file only when the container is removed, so a container that runs for months keeps months of output.
Edge cases / notes
docker logswithsyslogorjournalddrivers works only for some drivers;localandjson-filesupport it,syslogdoes not on older versions.- journald driver stores logs in the system journal, so set
SystemMaxUse=injournald.confinstead. - Build cache and images also fill disks;
docker system dfshows them, anddocker builder prunereclaims cache. - Volumes with database data are not affected by log settings; never prune volumes casually.
Next steps
- If the disk is already full, follow Fix a Django Server With a Full Disk.
- Make app logs worth keeping with Django Logging Setup for Production.
FAQ
Does Docker rotate container logs by default?
No. The default json-file driver has no size limit unless you set max-size.
Can I delete the json.log file?
Truncate it instead. Deleting it does not free space while the container is running.
Why did my daemon.json change not apply?
Existing containers keep their log settings. Recreate them after restarting Docker.
Which driver should I use?
local for compact rotated logs on the host, or json-file with limits if a shipper reads those files.