services: portainer: image: portainer/portainer-ce:latest container_name: portainer restart: unless-stopped # DIRECT ACCESS: Bind only to VPN gateway IP ports: - "10.8.0.1:9002:9000" # Port 9002 to avoid conflict with MinIO (port 9000) networks: - monitoring-internal volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - portainer-data:/data # Removed Traefik labels - direct access only prometheus: image: prom/prometheus:latest container_name: prometheus restart: unless-stopped user: "65534:65534" # DIRECT ACCESS: Bind only to VPN gateway IP ports: - "10.8.0.1:9090:9090" networks: - monitoring-internal - app-internal volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - ./prometheus/alerts.yml:/etc/prometheus/alerts.yml:ro - prometheus-data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--storage.tsdb.retention.time=30d' - '--web.console.libraries=/usr/share/prometheus/console_libraries' - '--web.console.templates=/usr/share/prometheus/consoles' - '--web.enable-lifecycle' # Removed Traefik labels - direct access only healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/healthy"] interval: 30s timeout: 10s retries: 3 grafana: image: grafana/grafana:latest container_name: grafana restart: unless-stopped # DIRECT ACCESS: Bind only to VPN gateway IP ports: - "10.8.0.1:3001:3000" networks: - monitoring-internal - app-internal environment: # Updated root URL for direct IP access - GF_SERVER_ROOT_URL=http://10.8.0.1:3001 - GF_SECURITY_ADMIN_USER=${GRAFANA_ADMIN_USER} - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD} - GF_USERS_ALLOW_SIGN_UP=false - GF_INSTALL_PLUGINS=${GRAFANA_PLUGINS} - GF_LOG_LEVEL=info - GF_ANALYTICS_REPORTING_ENABLED=false # Performance: Disable external connections to grafana.com - GF_PLUGIN_GRAFANA_COM_URL= - GF_CHECK_FOR_UPDATES=false - GF_CHECK_FOR_PLUGIN_UPDATES=false # Disable background plugin installer completely - GF_FEATURE_TOGGLES_ENABLE=disablePluginInstaller - GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS= volumes: - grafana-data:/var/lib/grafana - ./grafana/grafana.ini:/etc/grafana/grafana.ini:ro - ./grafana/provisioning:/etc/grafana/provisioning:ro - ./grafana/dashboards:/var/lib/grafana/dashboards:ro # Removed Traefik labels - direct access only depends_on: prometheus: condition: service_healthy healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"] interval: 30s timeout: 10s retries: 3 node-exporter: image: prom/node-exporter:latest container_name: node-exporter restart: unless-stopped networks: - app-internal volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)' healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9100/metrics"] interval: 30s timeout: 10s retries: 3 cadvisor: image: gcr.io/cadvisor/cadvisor:latest container_name: cadvisor restart: unless-stopped privileged: true networks: - app-internal 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 healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/healthz"] interval: 30s timeout: 10s retries: 3 volumes: portainer-data: name: portainer-data prometheus-data: name: prometheus-data grafana-data: name: grafana-data networks: # New internal network for monitoring services monitoring-internal: name: monitoring-internal driver: bridge app-internal: external: true