chore(部署): 增加 Docker 部署配置

关键改动:

- 新增本地和生产 Docker Compose、Web/Server Dockerfile 与 Nginx 模板

- 增加生产部署校验脚本、环境变量示例和 Prisma 初始迁移

- 更新部署文档、README 和架构/决策/流程/路线图说明

Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
Script Generator
2026-07-01 16:04:18 +08:00
parent 06b4aad7a4
commit 61f4ca51f1
22 changed files with 1051 additions and 1 deletions

View File

@@ -123,6 +123,25 @@ DevTask 没有"已完成"状态,"已提测"就是终态——开发交付完
**后续 V2.2(计划):**`app_data` 中稳定的数据形状逐步拆成关系表和领域 CRUD API。拆表前不要恢复业务 localStorage 缓存,避免线上部署后出现多端数据分叉。
## 生产部署层2026-07-01
当前仓库已补齐云服务器生产部署基线:
- `Dockerfile.web`:以 monorepo 根目录为 build context构建 `@ftb/shared` 和 Next.js 前端,运行 `pnpm --filter web start`
- `Dockerfile.server`:构建 `@ftb/shared` 和 NestJS 后端,执行 `prisma generate`,运行 `pnpm --filter server start:prod`
- `docker-compose.prod.yml`:编排 `web``server``postgres``redis``nginx` 五个服务,服务间通过 Docker 内网通信,对外只暴露 Nginx 80 端口。
- `docker-compose.local.yml`:本地服务器/局域网部署入口,同样编排五个服务,默认对外暴露 `8080`,使用独立 `local_*` volumes避免与云服务器生产数据混用。
- `deploy/nginx/default.conf.template`:同域反向代理,`/api/` 转发到 NestJS其他路径转发到 Next.js。
- `.env.production.example` / `.env.local-server.example`:生产和本地服务器配置模板;正式部署复制为 `.env.production``.env.local-server`,不提交真实密钥。
生产持久化边界:
- 业务主数据在 PostgreSQL `postgres_data` volume 中。
- Redis AOF 在 `redis_data` volume 中。
- AI Provider 配置文件在 `server_data` volume 中,对应容器路径 `/app/apps/server/data`
生产数据库初始化使用 Prisma migration`pnpm --filter server db:deploy`。本地开发仍可使用 `pnpm db:migrate`
## 权限模型(轻量)
V1 仅做前端校验,无后端鉴权:

View File

@@ -460,3 +460,19 @@
- 版本级统计、工作台和风险预警统计包含无需求ID分组任务/用例;需求级进度和需求关闭条件只统计带正式 `requirementId` 的 DevTask。
**理由**:关联需求代表人为确认的正式范围,不能被 AI 静默扩写;但原型批注也是当前版本真实交付范围的重要证据,不应该因为没有 REQID 被丢掉。无需求ID分组让任务和用例完整进入执行视图同时保持需求池干净、关联需求列表可信。
## 38. 生产部署采用 Docker Compose + Nginx 同域反代
**问题**:系统已经从浏览器 localStorage 迁到 NestJS + PostgreSQL `app_data`,可以部署到云服务器,但如果只依赖开发命令,生产环境会缺少统一编排、健康检查、持久卷、反向代理和数据库初始化流程。
**决策**
- 生产部署使用 `docker-compose.prod.yml` 编排 `web``server``postgres``redis``nginx`
- 本地服务器/局域网部署使用 `docker-compose.local.yml`,同样跑完整五服务栈,但默认绑定宿主机 `8080`,并使用独立 `local_*` volumes。
- `web``server` 分别用 `Dockerfile.web``Dockerfile.server` 从 monorepo 根目录构建,先构建 `@ftb/shared`,再构建各自应用。
- 对外只暴露 Nginx 80 端口;`/api/` 转发到 NestJS其他路径转发到 Next.js。
- 前端生产默认使用同域 API`NEXT_PUBLIC_API_URL=/api/v1`,避免浏览器跨域配置。
- PostgreSQL、Redis 和 server 文件数据分别使用 `postgres_data``redis_data``server_data` 命名卷持久化。
- 数据库生产初始化走 `prisma migrate deploy`,仓库保留初始 migration本地开发仍使用 `prisma migrate dev`
- HTTPS 先交给云负载均衡、CDN、宿主机证书工具或外层 Nginx 终止Compose 内置 Nginx 保持 HTTP 反代基线。
**理由**Docker Compose 足够覆盖当前单机云服务器和本地服务器形态,部署成本低、可读性强,也符合现阶段 2 核 4G 云主机目标。同域反代能减少 CORS 和公网端口暴露面。本地服务器默认 8080避免占用 80 端口或要求管理员权限;云服务器继续使用 80 作为外层入口。HTTPS 证书自动续期和域名接入在不同云环境差异较大,先作为外层能力处理,避免把生产部署模板绑死在某一种证书方案上。

210
docs/deployment.md Normal file
View File

@@ -0,0 +1,210 @@
# 部署指南
本文档覆盖三种部署方式:
- 本地开发:前端、后端直接用 pnpm 跑PostgreSQL 和 Redis 用 `docker-compose.yml` 启动。
- 本地服务器部署:一台本机或局域网服务器用 `docker-compose.local.yml` 跑完整 Web、Server、PostgreSQL、Redis、Nginx。
- 云服务器生产:所有服务用 `docker-compose.prod.yml` 编排Nginx 对外暴露 HTTP业务数据写入 PostgreSQL volumeAI 配置文件写入 server volume。
## 本地开发部署
```bash
pnpm install
cp apps/server/.env.example apps/server/.env
docker compose up -d
pnpm db:migrate
pnpm dev
```
访问地址:
- Web: `http://localhost:3000`
- API: `http://localhost:3001/api/v1`
- API 健康探测:`http://localhost:3001/api/v1/config/ai`
## 本地服务器部署
本地服务器部署适合这些场景:
- 在自己的电脑上用接近生产的方式跑完整系统。
- 在办公室内网或测试机上给同事访问。
- 不想安装 Node/pnpm 到目标机器,只想用 Docker Compose 管理全栈服务。
它不同于“本地开发”:不会用 `pnpm dev`,而是构建生产镜像并通过 Nginx 统一入口访问。
### 1. 准备配置
```bash
cp .env.local-server.example .env.local-server
```
默认访问地址是:
```text
http://localhost:8080
```
如果要给局域网其他人访问,修改 `.env.local-server`
```env
LOCAL_ACCESS_HOST=192.168.1.50
NEXTAUTH_URL=http://192.168.1.50:8080
```
其中 `192.168.1.50` 换成这台机器在局域网里的 IP。`NEXT_PUBLIC_API_URL` 保持 `/api/v1`,让浏览器通过同一个 Nginx 入口访问后端。
### 2. 校验并启动
```bash
pnpm deploy:verify
pnpm deploy:local:build
pnpm deploy:local:up
```
首次启动后执行数据库 migration
```bash
docker compose --env-file .env.local-server -f docker-compose.local.yml exec server pnpm --filter server db:deploy
```
检查服务:
```bash
docker compose --env-file .env.local-server -f docker-compose.local.yml ps
curl http://localhost:8080/api/v1/config/ai
```
停止本地服务器部署:
```bash
pnpm deploy:local:down
```
本地服务器部署使用独立 volume
- `local_postgres_data`
- `local_redis_data`
- `local_server_data`
这些 volume 与云服务器生产部署的 `postgres_data``redis_data``server_data` 分开,避免本机测试数据和生产数据混在一起。
## 云服务器生产部署
### 1. 准备服务器
推荐一台 2 核 4G 以上 Linux 云服务器,并安装:
- Docker Engine
- Docker Compose v2
- Git
开放 80 端口。如果 HTTPS 由云厂商负载均衡、CDN 或宝塔/Nginx 外层托管,则在外层终止 TLS 后转发到本机 80。
### 2. 准备配置
```bash
cp .env.production.example .env.production
```
必须修改这些值:
- `POSTGRES_PASSWORD`:强密码。
- `DATABASE_URL`:密码要与 `POSTGRES_PASSWORD` 一致,主机保持 `postgres`
- `SERVER_NAME`:你的域名,例如 `pm.example.com`
- `NEXTAUTH_URL`:正式访问地址,例如 `https://pm.example.com`
- `NEXTAUTH_SECRET`:随机长密钥。
- `NEXT_PUBLIC_API_URL`:同域部署保持 `/api/v1`;如果前后端分域,填完整 API 地址。
- `ANTHROPIC_API_KEY`:可先留空或占位,后续也可以在 `/admin/ai-config` 页面配置。
### 3. 校验部署文件
```bash
pnpm deploy:verify
```
该命令会检查 `Dockerfile.web``Dockerfile.server``docker-compose.prod.yml``docker-compose.local.yml`、Nginx 模板、env 示例和本文档是否齐全。
### 4. 构建并启动
```bash
docker compose --env-file .env.production -f docker-compose.prod.yml build
docker compose --env-file .env.production -f docker-compose.prod.yml up -d
```
首次启动后执行数据库迁移:
```bash
docker compose --env-file .env.production -f docker-compose.prod.yml exec server pnpm --filter server db:deploy
```
然后检查服务状态:
```bash
docker compose --env-file .env.production -f docker-compose.prod.yml ps
curl http://localhost/api/v1/config/ai
```
## Nginx 路由
`deploy/nginx/default.conf.template` 使用官方 Nginx 镜像的模板机制生成配置:
- `/api/` 转发到 `server:3001`
- `/` 转发到 `web:3000`
- `X-Forwarded-Proto``X-Forwarded-For` 等反向代理头会透传给后端
生产 Compose 默认只监听 HTTP 80。HTTPS 建议优先交给云负载均衡、CDN 或宿主机外层证书管理工具;如果要让本 Compose 内的 Nginx 直接处理 HTTPS可以在后续增加证书 volume 和 443 server block。
## 数据持久化
生产 Compose 使用三个命名 volume
- `postgres_data`PostgreSQL 数据库,包含业务主数据和 `app_data`
- `redis_data`Redis AOF 数据。
- `server_data`NestJS 写入的 AI Provider 配置文件,例如 `data/ai-config.json`
浏览器不再作为业务数据主存储。清浏览器缓存不会删除产品、项目、版本、任务、测试用例、Bug 等业务数据。
## 升级流程
```bash
git pull
pnpm deploy:verify
docker compose --env-file .env.production -f docker-compose.prod.yml build
docker compose --env-file .env.production -f docker-compose.prod.yml up -d
docker compose --env-file .env.production -f docker-compose.prod.yml exec server pnpm --filter server db:deploy
```
升级前建议先备份数据库:
```bash
docker compose --env-file .env.production -f docker-compose.prod.yml exec postgres pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" > ftb_pm_backup.sql
```
## 常见排查
后端是否启动:
```bash
curl http://localhost/api/v1/config/ai
```
数据库是否可用:
```bash
docker compose --env-file .env.production -f docker-compose.prod.yml exec postgres pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"
```
查看日志:
```bash
docker compose --env-file .env.production -f docker-compose.prod.yml logs -f server
docker compose --env-file .env.production -f docker-compose.prod.yml logs -f web
docker compose --env-file .env.production -f docker-compose.prod.yml logs -f nginx
```
如果前端能打开但数据为空,优先检查:
1. `NEXT_PUBLIC_API_URL` 是否为 `/api/v1` 或正确的完整 API 地址。
2. `curl http://localhost/api/v1/config/ai` 是否返回 200。
3. `server` 日志里是否有 Prisma 或 `DATABASE_URL` 错误。
4. 是否已执行 `pnpm --filter server db:deploy`

View File

@@ -6,6 +6,13 @@
### 已完成(按时间倒序)
**2026-07-01**
- 补齐云服务器生产部署基线:`Dockerfile.web``Dockerfile.server``docker-compose.prod.yml`、Nginx 反代模板和 `.env.production.example`
- 补齐本地服务器/局域网部署基线:`docker-compose.local.yml``.env.local-server.example``deploy:local:*` 脚本
- 新增生产数据库初始化 migration并提供 `pnpm db:deploy` / `pnpm --filter server db:deploy`
- 新增 `pnpm deploy:verify` 校验生产部署文件完整性
- 新增 `docs/deployment.md`,覆盖本地开发、云服务器部署、升级、备份和排查流程
**2026-06-24**
- 新增 NestJS `DataModule` + Prisma `AppData`,提供 `GET/PUT /api/v1/data/:key`
- 产品/项目/版本树、需求池、调研/产品方案/UI、开发任务、测试用例、Bug 改为服务端持久化

View File

@@ -282,3 +282,28 @@ AI 解读不由人工按钮触发。`at_risk`、`likely_delayed`、`blocked` 自
- AI 预估工时和手填执行预估工时本身是小时数,不再按日期过滤;只有从计划起止时间自动推导的执行预估会按工作日历计算。
- 加班记录使用 `overtime.calcDuration`,不受节假日过滤,但按项目管理口径计算:每个自然日默认最多 8h跨天中间日期按 8h结束晚于 18:00 的当天额外计入超出时长,避免把夜间空档当作打卡工时。
- 新建加班记录也使用工作日历日期选择器;节假日和周末可选,只提示不阻止。
## 生产部署流程
生产部署以 `docs/deployment.md` 为准,标准顺序如下:
本地服务器/局域网部署:
1. 复制 `.env.local-server.example``.env.local-server`,按需把 `LOCAL_ACCESS_HOST``NEXTAUTH_URL` 改为本机局域网 IP。
2. 运行 `pnpm deploy:verify`
3. 运行 `pnpm deploy:local:build` 构建镜像。
4. 运行 `pnpm deploy:local:up` 启动服务,默认访问 `http://localhost:8080`
5. 首次部署或升级后运行 `docker compose --env-file .env.local-server -f docker-compose.local.yml exec server pnpm --filter server db:deploy`
6.`curl http://localhost:8080/api/v1/config/ai` 验证 Nginx 到后端链路。
云服务器部署:
1. 复制 `.env.production.example``.env.production`,替换密码、域名、`NEXTAUTH_SECRET`、AI key 等真实值。
2. 运行 `pnpm deploy:verify`,确认生产 Docker、Compose、Nginx、env 示例和文档齐全。
3. 运行 `docker compose --env-file .env.production -f docker-compose.prod.yml build` 构建镜像。
4. 运行 `docker compose --env-file .env.production -f docker-compose.prod.yml up -d` 启动服务。
5. 首次部署或升级后运行 `docker compose --env-file .env.production -f docker-compose.prod.yml exec server pnpm --filter server db:deploy`
6.`curl http://localhost/api/v1/config/ai` 验证 Nginx 到后端链路。
7.`docker compose --env-file .env.production -f docker-compose.prod.yml ps``logs -f server/web/nginx` 排查健康状态。
生产环境不提交 `.env.production`。HTTPS 默认由外层负载均衡、CDN、宿主机证书工具或外层 Nginx 终止Compose 内置 Nginx 只承担同域 HTTP 反代。