Docker Compose Logging: Centralized Logs with Loki and Grafana
Set up centralized logging for your homelab with Grafana Loki. Aggregate Docker container logs, search, and visualize your self-hosted infrastructure.
Posted by
Related reading
Private Cloud vs Public Cloud: When to Self-Host and When Not To
Understand when self-hosting makes sense and when public cloud is better. A practical guide to choosing between private cloud homelab and AWS/GCP/Azure services.
Homelab Documentation: Wiki.js vs BookStack for Self-Hosted Wikis
Document your homelab setup with self-hosted wikis. Compare Wiki.js and BookStack for creating searchable documentation of your infrastructure and procedures.
Docker Security Scanning: Trivy and Dockle for Safe Containers
Scan your Docker images for vulnerabilities before deploying. Learn to use Trivy and Dockle to secure your self-hosted homelab container infrastructure.

Why Centralized Logging?
Running docker logs on each container doesn't scale. Centralized logging lets you search all your homelab logs in one place, set up alerts, and debug issues faster.
The PLG Stack
Promtail + Loki + Grafana: A lightweight alternative to the ELK stack, perfect for homelabs.
version: "3.8"
services:
loki:
image: grafana/loki:latest
ports:
- "3100:3100"
volumes:
- loki_data:/loki
command: -config.file=/etc/loki/local-config.yaml
promtail:
image: grafana/promtail:latest
volumes:
- /var/log:/var/log:ro
- /var/run/docker.sock:/var/run/docker.sock
- ./promtail-config.yml:/etc/promtail/config.yml
command: -config.file=/etc/promtail/config.yml
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
loki_data:
grafana_data:Promtail Configuration
# promtail-config.yml
server:
http_listen_port: 9080
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: docker
docker_sd_configs:
- host: unix:///var/run/docker.sock
relabel_configs:
- source_labels: ['__meta_docker_container_name']
target_label: containerUseful LogQL Queries
# All logs from a container
{container="nginx"}
# Errors only
{container=~".+"} |= "error"
# Count errors per container
sum by (container) (count_over_time({container=~".+"} |= "error" [1h]))