01The Logging Problem
Without log rotation, a single verbose container can exhaust all disk space within days or hours.
02Understanding Default Logging
1# Check current log driver for a container2docker inspect --format='{{.HostConfig.LogConfig.Type}}' container_name34# Find log file location5docker inspect --format='{{.LogPath}}' container_name67# Check log file sizes for all containers8sudo du -h /var/lib/docker/containers/*/*-json.log | sort -h910# View logs11docker logs container_name12docker logs --tail 100 container_name13docker logs --since 1h container_name14docker logs -f container_name # Follow03Configuring Log Rotation
1services: 2 app: 3 image: myapp:latest4 logging: 5 driver: json-file6 options: 7 max-size: "10m" # Rotate when file reaches 10MB8 max-file: "3" # Keep only 3 rotated files9 compress: "true" # Compress rotated files (Docker 20.10+)10 labels: "app,environment" # Include these labels in logs1112 # More aggressive rotation for verbose services13 debug-service: 14 image: debug:latest15 logging: 16 driver: json-file17 options: 18 max-size: "5m"19 max-file: "2"2021 # Use local driver for better performance22 high-traffic-app: 23 image: webapp:latest24 logging: 25 driver: local26 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
1# /etc/docker/daemon.json2{3 "log-driver": "json-file",4 "log-opts": {5 "max-size": "10m",6 "max-file": "3",7 "compress": "true"8 }9}1011# Apply changes and restart Docker12# sudo systemctl restart dockerAfter 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
1services: 2 # Send logs to syslog3 app-syslog: 4 image: myapp:latest5 logging: 6 driver: syslog7 options: 8 syslog-address: "udp://localhost:514"9 tag: "myapp/{{.Name}}"10 syslog-facility: "local0"1112 # Send logs to journald (systemd)13 app-journald: 14 image: myapp:latest15 logging: 16 driver: journald17 options: 18 tag: "myapp"1920 # Disable logging entirely (not recommended)21 noisy-service: 22 image: chatty:latest23 logging: 24 driver: noneFor journald logs: journalctl CONTAINER_NAME=myapp. For syslog, check your syslog server for the tagged entries.
06Centralized Logging Stack
1# Centralized logging with Loki2services: 3 loki: 4 image: grafana/loki:latest5 container_name: loki6 ports: 7 - "3100:3100"8 volumes: 9 - loki_data:/loki10 command: -config.file=/etc/loki/local-config.yaml1112 promtail: 13 image: grafana/promtail:latest14 container_name: promtail15 volumes: 16 - /var/log:/var/log:ro17 - /var/lib/docker/containers:/var/lib/docker/containers:ro18 - ./promtail-config.yml:/etc/promtail/config.yml19 command: -config.file=/etc/promtail/config.yml2021 grafana: 22 image: grafana/grafana:latest23 container_name: grafana24 ports: 25 - "3000:3000"26 environment: 27 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}28 volumes: 29 - grafana_data:/var/lib/grafana3031volumes: 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# Monitor log disk usage2df -h /var/lib/docker34# Find largest log files5sudo find /var/lib/docker/containers -name "*-json.log" -exec du -h {} + | sort -rh | head -1067# Truncate a specific container's logs (emergency)8sudo truncate -s 0 /var/lib/docker/containers/<container-id>/*-json.log910# Clean up with prune (removes stopped containers)11docker system prune -f