--- # Loki + Alloy + Grafana log aggregation stack # Place this file in a directory e.g. ~/docker/loki-stack/ # Run with: docker compose up -d networks: logging: driver: bridge services: # ── Loki: log storage and query engine ────────────────────────────────────── loki: image: grafana/loki:3.4.2 container_name: loki restart: unless-stopped networks: - logging ports: - "3100:3100" # Loki HTTP API (Alloy pushes here; Grafana queries here) volumes: - /var/lib/loki:/loki - /etc/loki:/etc/loki:ro command: -config.file=/etc/loki/loki.yml healthcheck: test: ["CMD-SHELL", "wget -q --spider http://localhost:3100/ready || exit 1"] interval: 30s timeout: 5s retries: 5 # ── Alloy: log collector / syslog receiver ─────────────────────────────────── alloy: image: grafana/alloy:v1.7.5 container_name: alloy restart: unless-stopped networks: - logging ports: - "5140:5140/udp" # Syslog UDP (for MikroTik and other network devices) - "5140:5140/tcp" # Syslog TCP - "12345:12345" # Alloy UI (optional, useful for debugging) volumes: - /etc/alloy/alloy.alloy:/etc/alloy/config.alloy:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro # Docker log access - /var/run/docker.sock:/var/run/docker.sock:ro # Docker metadata command: run /etc/alloy/config.alloy --server.http.listen-addr=0.0.0.0:12345 depends_on: loki: condition: service_healthy # ── Grafana: log query UI ──────────────────────────────────────────────────── grafana: image: grafana/grafana:11.5.2 container_name: grafana restart: unless-stopped networks: - logging ports: - "3098:3000" volumes: - /var/lib/grafana:/var/lib/grafana - /etc/grafana/grafana-datasources.yml:/etc/grafana/provisioning/datasources/loki.yml:ro environment: - GF_AUTH_ANONYMOUS_ENABLED=true # Remove if you want login - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin # Remove if you want login - GF_SECURITY_ADMIN_PASSWORD=changeme # Change this depends_on: loki: condition: service_healthy