services: # ── Loki (Log Aggregation) ──────────────────────────────────── loki: image: grafana/loki:3.3.2 ports: - '3100:3100' volumes: - ./services/monitoring/loki/loki-config.yml:/etc/loki/local-config.yaml - loki-data:/loki command: -config.file=/etc/loki/local-config.yaml restart: unless-stopped healthcheck: # BusyBox wget (used in Alpine images) doesn't support --no-verbose/--tries test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3100/ready'] interval: 15s timeout: 5s retries: 3 # ── Grafana (Log Viewer + Dashboards) ───────────────────────── grafana: image: grafana/grafana:11.4.0 ports: - '3000:3000' environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=lysnrai - GF_USERS_ALLOW_SIGN_UP=false volumes: - ./services/monitoring/grafana/provisioning:/etc/grafana/provisioning - ./services/monitoring/grafana/dashboards:/var/lib/grafana/dashboards - grafana-data:/var/lib/grafana depends_on: loki: condition: service_started restart: unless-stopped healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3000/api/health'] interval: 15s timeout: 5s retries: 3 # ── API Gateway (Traefik) ─────────────────────────────────── gateway: image: traefik:v3.3 command: - '--api.insecure=true' - '--providers.docker=true' - '--providers.docker.exposedbydefault=false' - '--entrypoints.web.address=:80' - '--accesslog=true' - '--accesslog.format=json' ports: - '80:80' - '8080:8080' # Traefik dashboard volumes: - /var/run/docker.sock:/var/run/docker.sock:ro depends_on: loki: condition: service_started restart: unless-stopped # ── Platform Service (Fastify + TypeScript) ───────────── # Consolidated: auth, audit, notifications, flags, blob, invitations, referrals, promos, # subscriptions, usage, plans, licenses, stripe, items, comments, votes, public platform-service: build: context: . dockerfile: services/platform-service/Dockerfile ports: - '4003:4003' env_file: - .env environment: - PORT=4003 # Local/dev convenience: ensure Cosmos DB + containers exist. - COSMOS_AUTO_INIT=true labels: - 'traefik.enable=true' - 'traefik.http.routers.platform.rule=PathPrefix(`/api`) || PathPrefix(`/public`) || PathPrefix(`/health`)' - 'traefik.http.services.platform.loadbalancer.server.port=4003' restart: unless-stopped healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4003/health'] interval: 30s timeout: 10s retries: 3 # ── Extraction Service (Fastify + TypeScript + Python sidecar) ── extraction-service: build: context: . dockerfile: services/extraction-service/Dockerfile ports: - '4005:4005' env_file: - .env environment: - PORT=4005 - PYTHON_SIDECAR_URL=http://localhost:4006 labels: - 'traefik.enable=true' - 'traefik.http.routers.extraction.rule=PathPrefix(`/api/extract`) || PathPrefix(`/api/tasks`)' - 'traefik.http.services.extraction.loadbalancer.server.port=4005' restart: unless-stopped healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4005/health'] interval: 30s timeout: 10s retries: 3 # ── Volumes ─────────────────────────────────────────────────────── volumes: loki-data: grafana-data: