name: pg_local_cache

services:
  monitoring-init:
    image: postgres:${POSTGRES_MAJOR:-16}-${POSTGRES_VARIANT:-bookworm}
    restart: "no"
    init: true
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    pids_limit: 64
    mem_limit: 128m
    environment:
      PGHOST: postgres
      PGPORT: "5432"
      PGDATABASE: ${POSTGRES_DB:-app}
      PGUSER: ${POSTGRES_USER:-postgres}
    secrets:
      - source: postgres_password
        target: postgres_password
        mode: 0444
      - source: monitor_password
        target: monitor_password
        mode: 0444
    volumes:
      - ./monitoring/postgres/provision-monitor.sh:/usr/local/bin/provision-pg-local-cache-monitor:ro
    tmpfs:
      - /tmp:rw,noexec,nosuid,nodev,size=8m,mode=1777
    entrypoint:
      - /usr/local/bin/provision-pg-local-cache-monitor
    depends_on:
      postgres:
        condition: service_healthy

  postgres-exporter:
    image: quay.io/prometheuscommunity/postgres-exporter:v0.19.1
    restart: unless-stopped
    init: true
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    pids_limit: 128
    mem_limit: 128m
    environment:
      DATA_SOURCE_URI: postgres:5432/${POSTGRES_DB:-app}?sslmode=disable&connect_timeout=5
      DATA_SOURCE_USER: local_cache_monitor
      DATA_SOURCE_PASS_FILE: /run/secrets/monitor_password
      PG_EXPORTER_COLLECTION_TIMEOUT: 5s
    command:
      - --extend.query-path=/etc/postgres_exporter/queries.yaml
      - --log.level=info
    secrets:
      - source: monitor_password
        target: monitor_password
        mode: 0444
    volumes:
      - ./monitoring/postgres-exporter/queries.yaml:/etc/postgres_exporter/queries.yaml:ro
    tmpfs:
      - /tmp:rw,noexec,nosuid,nodev,size=8m,mode=1777
    expose:
      - "9187"
    depends_on:
      monitoring-init:
        condition: service_completed_successfully

  prometheus:
    image: prom/prometheus:v3.12.0
    restart: unless-stopped
    init: true
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    pids_limit: 256
    mem_limit: 512m
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.path=/prometheus
      - --storage.tsdb.retention.time=15d
      - --storage.tsdb.retention.size=5GB
    volumes:
      - ./monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./monitoring/prometheus/alerts.yml:/etc/prometheus/alerts.yml:ro
      - prometheus_data:/prometheus
    tmpfs:
      - /tmp:rw,noexec,nosuid,nodev,size=16m,mode=1777
    expose:
      - "9090"
    depends_on:
      postgres-exporter:
        condition: service_started

  grafana:
    image: grafana/grafana:13.1.0
    restart: unless-stopped
    init: true
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    pids_limit: 256
    mem_limit: 384m
    environment:
      GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
      GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/grafana_admin_password
      GF_AUTH_ANONYMOUS_ENABLED: "false"
      GF_USERS_ALLOW_SIGN_UP: "false"
      GF_USERS_ALLOW_ORG_CREATE: "false"
      GF_SECURITY_DISABLE_GRAVATAR: "true"
      GF_ANALYTICS_REPORTING_ENABLED: "false"
      GF_ANALYTICS_CHECK_FOR_UPDATES: "false"
      GF_ANALYTICS_CHECK_FOR_PLUGIN_UPDATES: "false"
      GF_SERVER_ROOT_URL: ${GRAFANA_ROOT_URL:-http://localhost:3000}
      GF_LOG_MODE: console
    secrets:
      - source: grafana_admin_password
        target: grafana_admin_password
        mode: 0444
    volumes:
      - ./monitoring/grafana/provisioning:/etc/grafana/provisioning:ro
      - ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro
      - grafana_data:/var/lib/grafana
    tmpfs:
      - /tmp:rw,noexec,nosuid,nodev,size=32m,mode=1777
      - /var/log/grafana:rw,noexec,nosuid,nodev,size=16m,mode=0755
    ports:
      - 127.0.0.1:${GRAFANA_HOST_PORT:-3000}:3000
    depends_on:
      prometheus:
        condition: service_started

  cadvisor:
    image: ghcr.io/google/cadvisor:v0.57.0
    profiles:
      - host-metrics
    restart: unless-stopped
    privileged: true
    pids_limit: 256
    mem_limit: 256m
    command:
      - --docker_only=true
      - --housekeeping_interval=30s
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker:/var/lib/docker:ro
      - /dev/disk:/dev/disk:ro
    devices:
      - /dev/kmsg:/dev/kmsg
    expose:
      - "8080"

secrets:
  monitor_password:
    file: ./secrets/monitor_password
  grafana_admin_password:
    file: ./secrets/grafana_admin_password

volumes:
  prometheus_data:
  grafana_data:
