docker.recipes
Fundamentals7 min read

Docker Logging: Drivers, Rotation, and Collection

Configure logging properly to prevent disk exhaustion and enable effective debugging.

01The Logging Problem

Docker's default logging can fill your disk. Every container writes JSON logs with no size limit. A chatty application can generate gigabytes of logs, crashing your server. Proper logging configuration is essential for any self-hosted setup.

Without log rotation, a single verbose container can exhaust all disk space within days or hours.

02Understanding Default Logging

By default, Docker uses the json-file driver, storing logs in /var/lib/docker/containers/<id>/<id>-json.log. These logs persist until you remove the container and have no automatic rotation.
1# Check current log driver for a container
2docker inspect --format='{{.HostConfig.LogConfig.Type}}' container_name
3
4# Find log file location
5docker inspect --format='{{.LogPath}}' container_name
6
7# Check log file sizes for all containers
8sudo du -h /var/lib/docker/containers/*/*-json.log | sort -h
9
10# View logs
11docker logs container_name
12docker logs --tail 100 container_name
13docker logs --since 1h container_name
14docker logs -f container_name # Follow

03Configuring Log Rotation

The json-file and local drivers support built-in rotation. Set max-size and max-file to limit disk usage.
1services:
2 app:
3 image: myapp:latest
4 logging:
5 driver: json-file
6 options:
7 max-size: "10m" # Rotate when file reaches 10MB
8 max-file: "3" # Keep only 3 rotated files
9 compress: "true" # Compress rotated files (Docker 20.10+)
10 labels: "app,environment" # Include these labels in logs
11
12 # More aggressive rotation for verbose services
13 debug-service:
14 image: debug:latest
15 logging:
16 driver: json-file
17 options:
18 max-size: "5m"
19 max-file: "2"
20
21 # Use local driver for better performance
22 high-traffic-app:
23 image: webapp:latest
24 logging:
25 driver: local
26 options:
27 max-size: "50m"
28 max-file: "5"

The 'local' driver is faster than json-file and includes compression by default, but logs aren't in JSON format.

04Setting Global Defaults

Instead of configuring each container, set defaults in Docker daemon configuration. This applies to all containers that don't specify their own logging config.
1# /etc/docker/daemon.json
2{
3 "log-driver": "json-file",
4 "log-opts": {
5 "max-size": "10m",
6 "max-file": "3",
7 "compress": "true"
8 }
9}
10
11# Apply changes and restart Docker
12# sudo systemctl restart docker

After changing daemon.json, restart Docker with: sudo systemctl restart docker. Existing containers keep their original config.

Changing daemon.json requires a Docker restart. Existing containers keep their original logging config.

05Alternative Log Drivers

For integration with system logging or centralized log management, consider syslog or journald drivers.
1services:
2 # Send logs to syslog
3 app-syslog:
4 image: myapp:latest
5 logging:
6 driver: syslog
7 options:
8 syslog-address: "udp://localhost:514"
9 tag: "myapp/{{.Name}}"
10 syslog-facility: "local0"
11
12 # Send logs to journald (systemd)
13 app-journald:
14 image: myapp:latest
15 logging:
16 driver: journald
17 options:
18 tag: "myapp"
19
20 # Disable logging entirely (not recommended)
21 noisy-service:
22 image: chatty:latest
23 logging:
24 driver: none

For journald logs: journalctl CONTAINER_NAME=myapp. For syslog, check your syslog server for the tagged entries.

06Centralized Logging Stack

For production setups, ship logs to a central system. Here's a lightweight stack using Loki and Promtail.
1# Centralized logging with Loki
2services:
3 loki:
4 image: grafana/loki:latest
5 container_name: loki
6 ports:
7 - "3100:3100"
8 volumes:
9 - loki_data:/loki
10 command: -config.file=/etc/loki/local-config.yaml
11
12 promtail:
13 image: grafana/promtail:latest
14 container_name: promtail
15 volumes:
16 - /var/log:/var/log:ro
17 - /var/lib/docker/containers:/var/lib/docker/containers:ro
18 - ./promtail-config.yml:/etc/promtail/config.yml
19 command: -config.file=/etc/promtail/config.yml
20
21 grafana:
22 image: grafana/grafana:latest
23 container_name: grafana
24 ports:
25 - "3000:3000"
26 environment:
27 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
28 volumes:
29 - grafana_data:/var/lib/grafana
30
31volumes:
32 loki_data:
33 grafana_data:

Loki is designed for logs like Prometheus is for metrics—lightweight and perfect for self-hosted setups. Configure Promtail to scrape container logs.

07Logging Best Practices

**1. Always configure rotation** Set max-size and max-file on all containers, or set daemon defaults. **2. Use structured logging** JSON logs are easier to parse and search than plain text. **3. Include context** Add labels (container name, environment) to logs for filtering. **4. Don't log sensitive data** Passwords, tokens, and PII should never appear in logs. **5. Monitor log volume** Track disk usage; alert before it becomes critical. **6. Retain appropriately** Keep logs long enough for debugging, but not forever.
1# Monitor log disk usage
2df -h /var/lib/docker
3
4# Find largest log files
5sudo find /var/lib/docker/containers -name "*-json.log" -exec du -h {} + | sort -rh | head -10
6
7# Truncate a specific container's logs (emergency)
8sudo truncate -s 0 /var/lib/docker/containers/<container-id>/*-json.log
9
10# Clean up with prune (removes stopped containers)
11docker system prune -f