Files
Edu/infra/docker-compose.deploy.yml
SpecialX 4a0893ef52 feat(infra): 新增生产 Dockerfile 与部署 compose
- api-gateway/Dockerfile: 多阶段构建,golang:1.22-alpine → alpine:3.20,CGO_ENABLED=0 静态编译,非 root 运行

- teacher-portal/Dockerfile: 多阶段构建,node:20-alpine builder → runner,含 HEALTHCHECK

- docker-compose.prod.yml: 本地生产编排,3 服务,强制 DEV_MODE=false

- docker-compose.deploy.yml: 服务器部署用,镜像来自 Gitea Registry,通过 edu-shared 外部网络连接 MySQL/Redis

- deploy.env.example: 部署环境变量模板
2026-07-08 15:12:34 +08:00

106 lines
3.4 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 服务器部署用 Docker Compose
# 镜像来源Gitea Container Registry (git.eazygame.cn/xiner/edu/<service>:<tag>)
# 基础设施MySQL + Redis 已在服务器 Docker 中运行(不在此文件管理)
#
# 部署目录:/opt/edu/
# 部署命令CI 自动执行):
# IMAGE_TAG=latest docker compose pull && docker compose up -d
#
# 首次部署手动步骤:
# 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 login git.eazygame.cn -u <user> -p <token>
# 5. cd /opt/edu && IMAGE_TAG=latest docker compose up -d
name: edu
services:
api-gateway:
image: git.eazygame.cn/xiner/edu/api-gateway:${IMAGE_TAG:-latest}
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:
image: git.eazygame.cn/xiner/edu/classes:${IMAGE_TAG:-latest}
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:
image: git.eazygame.cn/xiner/edu/teacher-portal:${IMAGE_TAG:-latest}
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