# 本地测试用 Docker Compose(iam + teacher-bff + ai 联调) # 使用方式: # docker compose -f infra/docker-compose.test.yml up -d --build # # 依赖:edu-full_default 网络已存在(MySQL/Redis/Kafka 已在该网络) # 网络:复用 edu-full_default,使各服务可直连 edu-mysql/edu-redis/edu-kafka name: edu-test services: iam: build: context: .. dockerfile: services/iam/Dockerfile container_name: edu-iam-test restart: unless-stopped environment: # 生产模式:避免 pino-pretty 依赖(pruned by --prod) # DEV_MODE=true 仍可旁路鉴权 NODE_ENV: production PORT: "3002" GRPC_PORT: "50052" DATABASE_URL: mysql://edu:changeme@edu-mysql:3306/next_edu_cloud REDIS_URL: redis://edu-redis:6379 IAM_PRIVATE_KEY_PATH: /app/keys/iam-private.pem IAM_PUBLIC_KEY_PATH: /app/keys/iam-public.pem JWT_ISSUER: next-edu-cloud JWT_AUDIENCE: next-edu-cloud JWT_KEY_ID: iam-rs256-v1 KAFKA_BROKERS: kafka:29092 KAFKA_CLIENT_ID: iam-service LOG_LEVEL: info # 开发模式:接受 dev-token 旁路鉴权 DEV_MODE: "true" ports: - "3002:3002" - "50052:50052" volumes: - ../keys:/app/keys:ro healthcheck: test: ["CMD", "wget", "--quiet", "--spider", "http://localhost:3002/healthz"] interval: 10s timeout: 5s start_period: 30s retries: 5 networks: - edu-full teacher-bff: build: context: .. dockerfile: services/teacher-bff/Dockerfile container_name: edu-teacher-bff-test restart: unless-stopped environment: NODE_ENV: production PORT: "3003" GRAPHQL_PATH: /graphql TEACHER_BFF_DEV_MODE: "true" REDIS_URL: redis://edu-redis:6379 IAM_GRPC_TARGET: iam:50052 IAM_SERVICE_URL: http://iam:3002 CORE_EDU_GRPC_TARGET: core-edu:50053 CONTENT_GRPC_TARGET: content:50054 DATA_ANA_GRPC_TARGET: data-ana:50055 MSG_GRPC_TARGET: msg:50056 MSG_SERVICE_URL: http://msg:3007 AI_GRPC_TARGET: ai:50058 LOG_LEVEL: info ports: - "3003:3003" depends_on: iam: condition: service_healthy healthcheck: test: ["CMD", "wget", "--quiet", "--spider", "http://localhost:3003/healthz"] interval: 10s timeout: 5s start_period: 20s retries: 5 networks: - edu-full ai: build: context: ../services/ai dockerfile: Dockerfile container_name: edu-ai-test restart: unless-stopped environment: # HTTP/gRPC 端口 HTTP_PORT: "3008" GRPC_PORT: "50058" # 开发模式(旁路鉴权,dev-token) DEV_MODE: "true" LOG_LEVEL: info # 基础设施 REDIS_URL: redis://edu-redis:6379/0 KAFKA_BOOTSTRAP_SERVERS: kafka:29092 KAFKA_AI_USAGE_TOPIC: edu.ai.usage # 下游 gRPC 端点(edu-full_default 网络内服务名解析) # content 服务未启动 → connect 失败但不阻断启动,调用时抛 AIError CONTENT_GRPC_ENDPOINT: content:50054 DATA_ANA_GRPC_ENDPOINT: data-ana:50055 IAM_GRPC_ENDPOINT: iam:50052 # LLM 配置(测试环境不配 API key,LLM 功能降级,HTTP 端点仍可调) OPENAI_API_KEY: "" OPENAI_BASE_URL: https://api.openai.com/v1 ANTHROPIC_API_KEY: "" BAICHUAN_API_KEY: "" OLLAMA_BASE_URL: "" LLM_PROVIDER_PRIORITY: openai,anthropic,baichuan,local_ollama DEFAULT_CHAT_MODEL: gpt-4o-mini DEFAULT_QUESTION_MODEL: gpt-4o-mini # 可观测性(jaeger 已在 edu-full_default 网络中) OTEL_EXPORTER_OTLP_ENDPOINT: http://edu-jaeger:4318 ports: - "3008:3008" - "50058:50058" depends_on: iam: condition: service_healthy healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:3008/healthz')"] interval: 10s timeout: 5s start_period: 30s retries: 5 networks: - edu-full networks: edu-full: external: true name: edu-full_default