services: # PostgreSQL Database postgres: image: postgres:15-alpine container_name: knowfoolery-postgres env_file: - .env environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} ports: - "${POSTGRES_PORT}:5432" volumes: - postgres_data:/var/lib/postgresql/data - ./init-scripts:/docker-entrypoint-initdb.d healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 networks: - knowfoolery-network # Redis Cache redis: image: redis:7-alpine container_name: knowfoolery-redis env_file: - .env ports: - "${REDIS_PORT}:6379" volumes: - redis_data:/data command: redis-server --appendonly yes healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 networks: - knowfoolery-network # API Gateway Service (Go Fiber) gateway-service: image: golang:1.25-alpine container_name: knowfoolery-gateway-service working_dir: /workspace/backend/services/gateway-service command: sh -c "go run ./cmd/main.go" env_file: - .env environment: GATEWAY_INTERNAL_PORT: ${GATEWAY_INTERNAL_PORT} GAME_SESSION_BASE_URL: http://host.docker.internal:${GAME_SESSION_PORT} QUESTION_BANK_BASE_URL: http://host.docker.internal:${QUESTION_BANK_PORT} USER_SERVICE_BASE_URL: http://host.docker.internal:${USER_SERVICE_PORT} LEADERBOARD_BASE_URL: http://host.docker.internal:${LEADERBOARD_PORT} ADMIN_SERVICE_BASE_URL: http://host.docker.internal:${ADMIN_SERVICE_PORT} volumes: - ../../:/workspace extra_hosts: - "host.docker.internal:host-gateway" depends_on: redis: condition: service_started networks: - knowfoolery-network profiles: - gateway # Public NGINX entrypoint for gateway nginx: image: nginx:1.27-alpine container_name: knowfoolery-nginx env_file: - .env ports: - "${GATEWAY_PORT}:8086" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf:ro depends_on: gateway-service: condition: service_started networks: - knowfoolery-network profiles: - gateway # Zitadel Authentication (optional for initial setup) zitadel: image: ghcr.io/zitadel/zitadel:latest container_name: knowfoolery-zitadel command: start-from-init --masterkeyFromEnv --tlsMode disabled env_file: - .env environment: ZITADEL_MASTERKEY: ${ZITADEL_MASTERKEY} ZITADEL_DATABASE_COCKROACH_HOST: crdb ZITADEL_EXTERNALSECURE: false ZITADEL_FIRSTINSTANCE_ORG_NAME: ${ZITADEL_ORG_NAME} ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME: ${ZITADEL_ADMIN_USERNAME} ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD: ${ZITADEL_ADMIN_PASSWORD} ports: - "${ZITADEL_PORT}:8080" depends_on: crdb: condition: service_healthy networks: - knowfoolery-network profiles: - auth # CockroachDB for Zitadel crdb: image: cockroachdb/cockroach:latest container_name: knowfoolery-crdb command: start-single-node --insecure --http-addr :9090 env_file: - .env ports: - "${CRDB_PORT}:26257" - "${CRDB_HTTP_PORT}:9090" volumes: - crdb_data:/cockroach/cockroach-data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9090/health?ready=1"] interval: 10s timeout: 5s retries: 10 networks: - knowfoolery-network profiles: - auth # Prometheus Metrics prometheus: image: prom/prometheus:latest container_name: knowfoolery-prometheus env_file: - .env ports: - "${PROMETHEUS_PORT}:9090" volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.enable-lifecycle' networks: - knowfoolery-network profiles: - observability # Grafana Dashboards grafana: image: grafana/grafana:latest container_name: knowfoolery-grafana env_file: - .env ports: - "${GRAFANA_PORT}:3000" environment: GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER} GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD} GF_USERS_ALLOW_SIGN_UP: false volumes: - grafana_data:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning depends_on: - prometheus networks: - knowfoolery-network profiles: - observability # Jaeger Tracing jaeger: image: jaegertracing/all-in-one:latest container_name: knowfoolery-jaeger env_file: - .env ports: - "${JAEGER_UI_PORT}:16686" # UI - "${JAEGER_COLLECTOR_PORT}:14268" # Collector HTTP - "${JAEGER_AGENT_PORT}:6831/udp" # Agent environment: COLLECTOR_ZIPKIN_HOST_PORT: ":9411" networks: - knowfoolery-network profiles: - observability volumes: postgres_data: redis_data: crdb_data: prometheus_data: grafana_data: networks: knowfoolery-network: driver: bridge