# 本地启动手册(Local Dev Runbook) > 版本:1.0 > 日期:2026-07-08 > 适用范围:Edu 微服务(P1 阶段:api-gateway + classes + teacher-portal) > 关联文档:[project_rules](../../.trae/rules/project_rules.md)、[004 架构影响地图](../architecture/004_architecture_impact_map.md)、[known-issues](../troubleshooting/known-issues.md) --- ## 1. 环境依赖 | 工具 | 版本要求 | 验证命令 | 说明 | | -------------- | -------- | ------------------------ | -------------------------- | | Node.js | ≥ 20 | `node -v` | LTS 版本 | | pnpm | ≥ 9 | `pnpm -v` | `corepack enable` 自动启用 | | Go | 1.22+ | `go version` | api-gateway 编译 | | Docker | 24+ | `docker version` | 基础设施容器化 | | Docker Compose | v2+ | `docker compose version` | 编排基础设施 | | Git | 2.30+ | `git --version` | husky hooks 需要 | > Windows 用户:建议在 PowerShell 或 Git Bash 中执行。Go 工具链若不在 PATH,临时加入:`$env:Path = "C:\Program Files\Go\bin;" + $env:Path` --- ## 2. 服务端口分配 | 服务 | 端口 | 语言/框架 | 启动方式 | 健康检查 | | -------------- | ---- | ------------ | ------------------- | ----------------- | | MySQL | 3306 | Docker | `docker compose up` | `mysqladmin ping` | | Redis | 6379 | Docker | `docker compose up` | `redis-cli ping` | | api-gateway | 8080 | Go (Gin) | `go run main.go` | `GET /healthz` | | classes | 3001 | NestJS (TS) | `pnpm dev` | `GET /healthz` | | teacher-portal | 3000 | Next.js (TS) | `pnpm dev` | `GET /` | | iam | 3002 | NestJS | P2 阶段 | — | | teacher-bff | 3003 | NestJS | P2 阶段 | — | > 端口冲突排查:`netstat -ano \| findstr :8080`(Windows) --- ## 3. 本地开发模式(DEV_MODE) ### 3.1 首次准备 ```bash # 1. 克隆仓库 git clone Edu cd Edu # 2. 安装依赖 pnpm install # 3. 配置环境变量 cp .env.example .env # 编辑 .env,确认: # DEV_MODE=true ← 本地联调用 # JWT_SECRET=p1-dev-secret-change-in-production # DATABASE_URL=mysql://edu:changeme@localhost:3306/next_edu_cloud # REDIS_URL=redis://localhost:6379 # 4. 架构扫描(更新 arch.db) pnpm run arch:scan ``` ### 3.2 启动基础设施 ```bash # 启动 MySQL + Redis(最小基础设施) docker compose -f infra/docker-compose.minimal.yml up -d # 验证健康 docker compose -f infra/docker-compose.minimal.yml ps # 状态应为 healthy # (可选)国内镜像源加速:infra/docker-compose.minimal.override.yml 已配置 daocloud 镜像 ``` ### 3.3 启动应用服务(三个终端) #### 终端 1:api-gateway(:8080) ```bash cd services/api-gateway # Windows:若 Go 不在 PATH,先设置 $env:Path = "C:\Program Files\Go\bin;" + $env:Path # 设置开发模式环境变量 $env:DEV_MODE="true" $env:JWT_SECRET="p1-dev-secret-change-in-production" # 启动 go run main.go ``` 验证:`curl http://localhost:8080/healthz` → 200 OK #### 终端 2:classes 服务(:3001) ```bash # 在项目根目录 pnpm --filter @edu/classes-service dev ``` 验证:`curl http://localhost:3001/healthz` → 200 OK > 注:classes 的 HealthModule 需注册到 AppModule,当前若返回 404 见 [known-issues] #### 终端 3:teacher-portal(:3000) ```bash # 在项目根目录 pnpm --filter @edu/teacher-portal dev ``` 验证:浏览器访问 `http://localhost:3000` → 班级管理页面 ### 3.4 一键启动(可选) ```bash # 并行启动所有子包的 dev 脚本(含 api-gateway 需 go run,不会自动启动) pnpm dev ``` > 注:`pnpm dev` 仅启动 pnpm workspace 内的 TS 服务。api-gateway 是 Go 服务,需单独 `go run`。 ### 3.5 联调验证 ```bash # 1. 直接访问 api-gateway(带 dev-token) curl -H "Authorization: Bearer dev-token" http://localhost:8080/api/v1/classes # 预期:200 OK + 班级列表 JSON # 2. 通过 teacher-portal 代理访问 curl -H "Authorization: Bearer dev-token" http://localhost:3000/api/v1/classes # 预期:200 OK(经 Next.js rewrites → api-gateway → classes) # 3. 浏览器访问 # http://localhost:3000 → 班级管理页面,自动加载班级列表 ``` ### 3.6 dev-token 说明 - `DEV_MODE=true` 时,api-gateway 接受 `Authorization: Bearer dev-token` - 注入固定身份:`x-user-id: dev-user`,`x-user-roles: teacher,admin` - **仅限本地联调,生产环境必须 `DEV_MODE=false`** --- ## 4. 生产模式(Docker Compose) ### 4.1 构建镜像 ```bash # 构建三个应用服务镜像 docker compose -f infra/docker-compose.prod.yml build ``` ### 4.2 启动完整栈 ```bash # 1. 先启动基础设施(MySQL + Redis) docker compose -f infra/docker-compose.minimal.yml up -d # 2. 启动应用服务 docker compose -f infra/docker-compose.prod.yml up -d # 3. 查看状态 docker compose -f infra/docker-compose.prod.yml ps # 所有服务应为 healthy # 4. 查看日志 docker compose -f infra/docker-compose.prod.yml logs -f api-gateway ``` ### 4.3 生产环境配置要点 | 配置项 | 生产值 | 说明 | | -------------- | ---------------- | ----------------------------------------------- | | `DEV_MODE` | `false` | docker-compose.prod.yml 强制设为 false | | `JWT_SECRET` | 强随机值 | 替换 `p1-dev-secret-change-in-production` | | `DATABASE_URL` | 生产数据库连接 | 容器内用 `host.docker.internal` 或 compose 网络 | | `NODE_ENV` | `production` | teacher-portal 启用生产优化 | | `LOG_LEVEL` | `info` 或 `warn` | 生产日志级别 | ### 4.4 生产验证 ```bash # 健康检查 curl http://localhost:8080/healthz # api-gateway curl http://localhost:3001/healthz # classes curl http://localhost:3000/ # teacher-portal # 鉴权验证(生产模式 dev-token 应被拒绝) curl -H "Authorization: Bearer dev-token" http://localhost:8080/api/v1/classes # 预期:401 INVALID_TOKEN # 真实 JWT 访问(需 IAM 签发) curl -H "Authorization: Bearer " http://localhost:8080/api/v1/classes # 预期:200 OK ``` ### 4.5 停止与清理 ```bash # 停止应用服务 docker compose -f infra/docker-compose.prod.yml down # 停止基础设施 docker compose -f infra/docker-compose.minimal.yml down # 清理数据卷(谨慎!会删除数据库数据) docker compose -f infra/docker-compose.minimal.yml down -v ``` --- ## 5. 单独构建与运行(裸机生产) ### 5.1 api-gateway ```bash cd services/api-gateway # 编译 go build -o bin/api-gateway ./main.go # 运行(生产环境变量) DEV_MODE=false JWT_SECRET= ./bin/api-gateway ``` ### 5.2 classes 服务 ```bash # 构建 pnpm --filter @edu/classes-service build # 运行(从 dist/ 启动) NODE_ENV=production PORT=3001 \ DATABASE_URL=mysql://edu:changeme@localhost:3306/next_edu_cloud \ REDIS_URL=redis://localhost:6379 \ node services/classes/dist/main.js ``` ### 5.3 teacher-portal ```bash # 构建 pnpm --filter @edu/teacher-portal build # 运行 NODE_ENV=production PORT=3000 \ API_GATEWAY_URL=http://localhost:8080 \ node apps/teacher-portal/node_modules/.bin/next start -p 3000 ``` --- ## 6. 常见问题 ### 6.1 ERR_TOO_MANY_REDIRECTS **症状**:浏览器访问 `:3000/api/v1/classes` 无限重定向。 **根因**:Gin 默认 `RedirectTrailingSlash=true`,`/classes` → 301 → `/classes/`,Next.js rewrites 代理形成循环。 **修复**:`main.go` 已设 `r.RedirectTrailingSlash = false`,并同时注册无尾斜杠与通配符路由。 ### 6.2 Docker Hub 拉取超时 **症状**:`docker compose up` 时 MySQL/Redis 镜像拉取超时。 **修复**:`infra/docker-compose.minimal.override.yml` 已配置 daocloud 镜像源,docker compose 会自动加载。 ### 6.3 classes DI 注入失败 **症状**:`TypeError: Cannot read properties of undefined (reading 'create')`。 **根因**:NestJS ESM 模式下 `emitDecoratorMetadata` 不工作。 **修复**:`ClassesService` 构造函数已加 `@Inject(ClassesRepository)` 显式指定 token。 ### 6.4 ESM import 缺 .js 后缀 **症状**:`error TS2307: Cannot find module './health.controller'`。 **修复**:ESM 模式下相对 import 必须带 `.js` 后缀(详见 project_rules §3.4)。 ### 6.5 JWT 401 INVALID_TOKEN **症状**:带 `dev-token` 仍返回 401。 **排查**: 1. 确认 `DEV_MODE=true` 环境变量已设置(api-gateway 进程) 2. 确认请求头格式:`Authorization: Bearer dev-token`(注意 Bearer 后空格) 3. 生产模式(`DEV_MODE=false`)下 dev-token 被拒绝是预期行为 ### 6.6 Go 工具链不在 PATH **症状**:Git Bash 或 PowerShell 中 `go: command not found`。 **修复**: ```powershell $env:Path = "C:\Program Files\Go\bin;" + $env:Path ``` --- ## 7. 数据库初始化 classes 服务使用 Drizzle ORM,首次运行需建表: ```bash # 生成迁移 pnpm --filter @edu/classes-service drizzle-kit generate # 执行迁移 pnpm --filter @edu/classes-service drizzle-kit migrate ``` > 若 `drizzle-kit` 未配置,可手动执行 `services/classes/src/db/schema.sql`(如存在)。 --- ## 8. 相关文档 - [项目规则](../../.trae/rules/project_rules.md) — 强制约束 - [004 架构影响地图](../architecture/004_architecture_impact_map.md) — 服务清单与调用关系 - [known-issues](../troubleshooting/known-issues.md) — 已知问题速查 - [Git 工作流](./git-workflow.md) — 提交与 PR 规范 - [多 AI 协作指南](./multi-ai-collaboration.md) — 多 Agent 并行开发流程