Files
Edu/docs/standards/local-dev-runbook.md
SpecialX d19285a977 docs(docs): 新增本地启动/多AI协作/CI-CD 使用手册
- local-dev-runbook.md: 8 章本地启动手册(环境依赖/端口分配/开发模式/生产模式/裸机运行/常见问题)

- multi-ai-collaboration.md: 15 章多AI协作文档(角色定义/模块分工/分支策略/PR流程/审核合并/跨模块变更)

- cicd-runbook.md: 10 章 CI/CD 使用手册(架构总览/一次性配置/日常使用/镜像管理/部署验证/回滚)

- README.md: 文档清单新增三个 runbook 链接
2026-07-08 15:14:30 +08:00

334 lines
9.9 KiB
Markdown
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.
# 本地启动手册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 <repo-url> 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 启动应用服务(三个终端)
#### 终端 1api-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
#### 终端 2classes 服务(:3001
```bash
# 在项目根目录
pnpm --filter @edu/classes-service dev
```
验证:`curl http://localhost:3001/healthz` → 200 OK
> classes 的 HealthModule 需注册到 AppModule当前若返回 404 见 [known-issues]
#### 终端 3teacher-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 <real-jwt>" 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=<your-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 并行开发流程