services: api: image: ${REGISTRY_URL:-ghcr.io/goodgo}/goodgo-api:${IMAGE_TAG:-latest} container_name: goodgo-api restart: unless-stopped ports: - '${API_PORT:-3001}:3001' environment: NODE_ENV: production DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME} REDIS_URL: redis://redis:6379 TYPESENSE_HOST: typesense TYPESENSE_PORT: 8108 TYPESENSE_API_KEY: ${TYPESENSE_API_KEY} JWT_SECRET: ${JWT_SECRET} MINIO_ENDPOINT: minio MINIO_PORT: 9000 MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY} MINIO_SECRET_KEY: ${MINIO_SECRET_KEY} AI_SERVICES_URL: http://ai-services:8000 depends_on: postgres: condition: service_healthy redis: condition: service_healthy typesense: condition: service_healthy healthcheck: test: ['CMD', 'node', '-e', "fetch('http://localhost:3001/health').then(r => { if (!r.ok) throw 1 })"] interval: 30s timeout: 5s retries: 5 start_period: 30s networks: - goodgo-net web: image: ${REGISTRY_URL:-ghcr.io/goodgo}/goodgo-web:${IMAGE_TAG:-latest} container_name: goodgo-web restart: unless-stopped ports: - '${WEB_PORT:-3000}:3000' environment: NODE_ENV: production NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://api:3001} depends_on: api: condition: service_healthy healthcheck: test: ['CMD', 'node', '-e', "fetch('http://localhost:3000').then(r => { if (!r.ok) throw 1 }).catch(() => process.exit(1))"] interval: 30s timeout: 5s retries: 3 start_period: 15s networks: - goodgo-net postgres: image: postgis/postgis:16-3.4 container_name: goodgo-postgres restart: unless-stopped ports: - '${DB_PORT:-5432}:5432' environment: POSTGRES_DB: ${DB_NAME} POSTGRES_USER: ${DB_USER} POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U ${DB_USER} -d ${DB_NAME}'] interval: 10s timeout: 5s retries: 5 start_period: 30s networks: - goodgo-net redis: image: redis:7-alpine container_name: goodgo-redis restart: unless-stopped command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD} --maxmemory 512mb --maxmemory-policy allkeys-lru volumes: - redis_data:/data healthcheck: test: ['CMD', 'redis-cli', '-a', '${REDIS_PASSWORD}', 'ping'] interval: 10s timeout: 5s retries: 5 start_period: 10s networks: - goodgo-net typesense: image: typesense/typesense:27.1 container_name: goodgo-typesense restart: unless-stopped environment: TYPESENSE_API_KEY: ${TYPESENSE_API_KEY} TYPESENSE_DATA_DIR: /data volumes: - typesense_data:/data healthcheck: test: ['CMD', 'curl', '-sf', 'http://localhost:8108/health'] interval: 10s timeout: 5s retries: 5 start_period: 15s networks: - goodgo-net minio: image: minio/minio:latest container_name: goodgo-minio restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ACCESS_KEY} MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY} volumes: - minio_data:/data healthcheck: test: ['CMD', 'mc', 'ready', 'local'] interval: 10s timeout: 5s retries: 5 start_period: 15s networks: - goodgo-net ai-services: image: ${REGISTRY_URL:-ghcr.io/goodgo}/goodgo-ai-services:${IMAGE_TAG:-latest} container_name: goodgo-ai-services restart: unless-stopped environment: AI_DEBUG: 'false' AI_LOG_LEVEL: info healthcheck: test: ['CMD', 'python', '-c', 'import httpx; httpx.get("http://localhost:8000/health").raise_for_status()'] interval: 30s timeout: 5s retries: 5 start_period: 30s networks: - goodgo-net prometheus: image: prom/prometheus:v2.51.0 container_name: goodgo-prometheus restart: unless-stopped command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.retention.time=30d' - '--web.enable-lifecycle' volumes: - ./monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - prometheus_data:/prometheus healthcheck: test: ['CMD', 'wget', '--spider', '-q', 'http://localhost:9090/-/healthy'] interval: 15s timeout: 5s retries: 3 start_period: 10s networks: - goodgo-net grafana: image: grafana/grafana:10.4.1 container_name: goodgo-grafana restart: unless-stopped ports: - '${GRAFANA_PORT:-3002}:3000' environment: GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER} GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD} GF_USERS_ALLOW_SIGN_UP: 'false' GF_SERVER_ROOT_URL: ${GRAFANA_ROOT_URL:-http://localhost:3002} volumes: - ./monitoring/grafana/provisioning:/etc/grafana/provisioning:ro - ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro - grafana_data:/var/lib/grafana depends_on: prometheus: condition: service_healthy healthcheck: test: ['CMD', 'wget', '--spider', '-q', 'http://localhost:3000/api/health'] interval: 15s timeout: 5s retries: 3 start_period: 15s networks: - goodgo-net volumes: pgdata: driver: local redis_data: driver: local typesense_data: driver: local minio_data: driver: local prometheus_data: driver: local grafana_data: driver: local networks: goodgo-net: driver: bridge name: goodgo-net