# 服务器部署用 Docker Compose(no-push 本地构建模式) # 镜像来源:CI 容器内本地 docker build(不推送到 registry) # 基础设施:MySQL + Redis 已在服务器 Docker 中运行(不在此文件管理) # # 部署目录:/opt/edu/ # 部署命令(CI 自动执行): # docker compose up -d --build --remove-orphans # # 首次部署手动步骤: # 1. sudo mkdir -p /opt/edu && sudo chown -R $USER:$USER /opt/edu # 2. cp infra/docker-compose.deploy.yml /opt/edu/docker-compose.yml # 3. cp infra/deploy.env.example /opt/edu/.env && 编辑填入生产密钥 # 4. docker compose up -d --build # # 注意:compose 文件中的 build.context 路径相对于 /opt/edu/ 目录 # CI 在 deploy 步骤会先把仓库 checkout 到 /opt/edu/repo/,再 cp compose 文件到 /opt/edu/ name: edu services: api-gateway: build: context: ./repo/services/api-gateway dockerfile: Dockerfile container_name: edu-api-gateway restart: unless-stopped environment: API_GATEWAY_PORT: ${API_GATEWAY_PORT:-8080} JWT_SECRET: ${JWT_SECRET} JWT_ISSUER: ${JWT_ISSUER:-next-edu-cloud} JWT_AUDIENCE: ${JWT_AUDIENCE:-next-edu-cloud} # 生产环境强制关闭 dev-token 旁路 DEV_MODE: "false" CLASSES_SERVICE_URL: http://classes:3001 IAM_SERVICE_URL: http://iam:3002 TEACHER_BFF_URL: http://teacher-bff:3003 OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://otel-collector:4318} LOG_LEVEL: ${LOG_LEVEL:-info} ports: - "${API_GATEWAY_PORT:-8080}:8080" depends_on: classes: condition: service_healthy healthcheck: test: ["CMD", "wget", "--quiet", "--spider", "http://localhost:8080/healthz"] interval: 30s timeout: 5s start_period: 10s retries: 3 networks: - edu-net - edu-shared classes: build: context: ./repo dockerfile: services/classes/Dockerfile container_name: edu-classes restart: unless-stopped environment: PORT: 3001 # 连接服务器已有的 MySQL(容器名 edu-mysql,需在 edu-shared 网络) DATABASE_URL: ${DATABASE_URL} REDIS_URL: ${REDIS_URL} KAFKA_BROKERS: ${KAFKA_BROKERS:-} OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://otel-collector:4318} LOG_LEVEL: ${LOG_LEVEL:-info} healthcheck: test: ["CMD", "wget", "--quiet", "--spider", "http://localhost:3001/healthz"] interval: 30s timeout: 5s start_period: 30s retries: 5 networks: - edu-net - edu-shared teacher-portal: build: context: ./repo dockerfile: apps/teacher-portal/Dockerfile container_name: edu-teacher-portal restart: unless-stopped environment: NODE_ENV: production PORT: 3000 API_GATEWAY_URL: http://api-gateway:8080 ports: - "${TEACHER_PORTAL_PORT:-3000}:3000" depends_on: api-gateway: condition: service_healthy healthcheck: test: ["CMD", "wget", "--quiet", "--spider", "http://localhost:3000/"] interval: 30s timeout: 5s start_period: 20s retries: 3 networks: - edu-net - edu-shared networks: # 应用服务内部网络 edu-net: driver: bridge # 与已有 MySQL/Redis 共享的网络 # 需确保 MySQL/Redis 容器已加入名为 edu-shared 的网络: # docker network create edu-shared (若不存在) # docker network connect edu-shared edu-mysql # docker network connect edu-shared edu-redis edu-shared: external: true