Container logs and how not to lose them
Where Docker logs are stored, how to limit their size so they don't fill up the disk, and what to do so records survive container recreation.
Updated August 23, 2026
When a service goes down, the log is the only source of truth. By default Docker writes it to a file next to the container and puts no cap on its size: a chatty application can fill the whole disk in a week.
How to read
docker logs -f --tail 100 <container>
docker compose logs -f app
docker compose logs --since 30m --timestamps app
docker logs <container> 2>&1 | grep -i error | tail -50
Worth remembering: Docker shows what the application writes to standard output and standard error. If it writes to its own file inside the container, docker logs will show nothing — you have to look for the log inside or redirect the output.
docker compose exec app ls -la /var/log
Cap the size right now
The global setting for all containers is /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": { "max-size": "20m", "max-file": "3" }
}
sudo systemctl restart docker
The setting applies to containers created after a restart. Running ones must be recreated. For a single service, the same goes into Compose:
services:
app:
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
The result: no more than 60 MB per service instead of unbounded growth.
Check the current size before it surprises you:
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail. You cannot trim a running file withrm— the space is not freed while Docker holds the descriptor. The right way: recreate the container orsudo truncate -s 0 <file>.
Make logs survive the container
The log file is deleted along with the container. If the history matters, hand it over to the system journal:
logging:
driver: journald
options:
tag: "myapp"
journalctl -t myapp -n 200 --since today
journalctl -t myapp -p err --since "2 days ago"
journald rotates records on its own and is capped by the SystemMaxUse setting in /etc/systemd/journald.conf. To check how much space it takes: journalctl --disk-usage.
For several services at once it is more convenient to collect everything in one place — for example, with a dedicated collector container that stores records in files by day. But start with journald: it is already there and costs nothing.
What to look for when debugging an outage
- The last 200 lines before the crash:
docker logs --tail 200 <container>. - Exit code:
docker inspect -f '{{.State.ExitCode}} {{.State.OOMKilled}}' <container>. Code 137 andtrueinOOMKilledmean the kernel killed the process because it ran out of memory — see resource limits. - The machine's system log:
sudo dmesg -T | tail -50will show out-of-memory kills and disk errors.
Common mistakes
- The disk filled up with logs and every service went down. Capping the size is a must right after installing Docker.
- Looking at the log of an already deleted container. After
docker compose downit is gone. Collect records intojournaldin advance. - Secrets in the log. Applications love printing connection strings with passwords. Anyone with access to the machine can read the log.
- Looking for the error in the text console. It is always 80×24 and long lines get cut off. To read logs, SSH or the “Screen” console is more convenient.