feat: add Promtail, Loki, and Grafana log aggregation stack (refs #86)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 31s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 35s
Deploy to Staging / Verify Staging (pull_request) Successful in 2m37s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 8s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped

- Add Promtail for Docker log scraping with container discovery
- Add Loki for log storage with 30-day retention
- Add Grafana with Loki datasource auto-provisioned
- Add IP whitelist middleware restricting Grafana to RFC1918 ranges
- Container count: 6 → 9

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eric Gullickson
2026-02-04 20:16:53 -06:00
parent 915f15c610
commit 1cf54fb254
5 changed files with 152 additions and 0 deletions

View File

@@ -264,6 +264,84 @@ services:
max-size: "10m"
max-file: "3"
# Log Aggregation - Loki
mvp-loki:
image: grafana/loki:2.9.0
container_name: mvp-loki
restart: unless-stopped
volumes:
- ./config/loki/config.yml:/etc/loki/config.yml:ro
- mvp_loki_data:/loki
command: -config.file=/etc/loki/config.yml
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:3100/ready || exit 1"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Log Aggregation - Promtail
mvp-promtail:
image: grafana/promtail:2.9.0
container_name: mvp-promtail
restart: unless-stopped
volumes:
- ./config/promtail/config.yml:/etc/promtail/config.yml:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
command: -config.file=/etc/promtail/config.yml
networks:
- backend
depends_on:
- mvp-loki
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Log Aggregation - Grafana
mvp-grafana:
image: grafana/grafana:10.0.0
container_name: mvp-grafana
restart: unless-stopped
environment:
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:-admin}
GF_USERS_ALLOW_SIGN_UP: "false"
volumes:
- ./config/grafana/datasources:/etc/grafana/provisioning/datasources:ro
- mvp_grafana_data:/var/lib/grafana
networks:
- backend
- frontend
depends_on:
- mvp-loki
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:3000/api/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
labels:
- "traefik.enable=true"
- "traefik.docker.network=motovaultpro_frontend"
- "traefik.http.routers.grafana.rule=Host(`logs.motovaultpro.com`)"
- "traefik.http.routers.grafana.entrypoints=websecure"
- "traefik.http.routers.grafana.tls=true"
- "traefik.http.routers.grafana.tls.certresolver=letsencrypt"
- "traefik.http.routers.grafana.middlewares=grafana-ipwhitelist@file"
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Network Definition
networks:
frontend:
@@ -302,3 +380,7 @@ volumes:
name: mvp_postgres_data
mvp_redis_data:
name: mvp_redis_data
mvp_loki_data:
name: mvp_loki_data
mvp_grafana_data:
name: mvp_grafana_data