Files
ftb-project-management/docs/deployment.md

9.8 KiB
Raw Blame History

部署指南

本文档覆盖三种部署方式:

  • 本地开发:前端、后端直接用 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。

本地开发部署

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. 准备配置

cp .env.local-server.example .env.local-server

默认访问地址是:

http://localhost:8080

如果要给局域网其他人访问,修改 .env.local-server

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. 校验并启动

pnpm deploy:verify
pnpm deploy:local:build
pnpm deploy:local:up

首次启动后执行数据库 migration

docker compose --env-file .env.local-server -f docker-compose.local.yml exec server pnpm --filter server db:deploy

检查服务:

docker compose --env-file .env.local-server -f docker-compose.local.yml ps
curl http://localhost:8080/api/v1/config/ai

停止本地服务器部署:

pnpm deploy:local:down

本地服务器部署使用独立 volume

  • local_postgres_data
  • local_redis_data
  • local_server_data

这些 volume 与云服务器生产部署的 postgres_dataredis_dataserver_data 分开,避免本机测试数据和生产数据混在一起。

云服务器生产部署

1. 准备服务器

推荐一台 2 核 4G 以上 Linux 云服务器,并安装:

  • Docker Engine
  • Docker Compose v2
  • Git

开放 80 端口。如果 HTTPS 由云厂商负载均衡、CDN 或宝塔/Nginx 外层托管,则在外层终止 TLS 后转发到本机 80。

2. 准备配置

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. 校验部署文件

pnpm deploy:verify

该命令会检查 Dockerfile.webDockerfile.serverdocker-compose.prod.ymldocker-compose.local.yml、Nginx 模板、env 示例和本文档是否齐全。

4. 构建并启动

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

然后检查服务状态:

docker compose --env-file .env.production -f docker-compose.prod.yml ps
curl http://localhost/api/v1/config/ai

全自动生产发布(推荐)

生产环境推荐走 .github/workflows/deploy-production.yml,不再要求部署侧手工执行 docker compose build 或手工判断是否需要 up

GitHub 仓库需要配置这些 Secrets

  • PROD_HOST:生产服务器地址。
  • PROD_USERSSH 用户。
  • PROD_SSH_KEYSSH 私钥。
  • PROD_APP_DIR:服务器上的项目目录。
  • GHCR_READ_TOKEN可选。GHCR 镜像为私有包时,用于服务器 docker login ghcr.io 拉镜像。

服务器首次准备仍然需要完成一次:

git clone <repo-url> ftb-project-management
cd ftb-project-management
cp .env.production.example .env.production

然后按实际环境改好 .env.production 里的数据库密码、域名、NEXTAUTH_SECRET、AI key 等。APP_VERSIONAPP_BUILD_TIMEWEB_IMAGESERVER_IMAGE 会由 GitHub Actions 在每次发布时自动更新。

之后只要代码合并或 push 到 masterActions 会自动执行:

  1. 用当前 commit SHA 构建 webserver Docker 镜像。
  2. 推送镜像到 GHCR镜像 tag 同时包含 commit SHA 和 master
  3. SSH 到生产服务器,git pull --ff-only origin master 更新 Compose 和部署脚本。
  4. 写入 .env.productionAPP_VERSIONAPP_BUILD_TIMEWEB_IMAGESERVER_IMAGE
  5. 执行 docker compose --env-file .env.production -f docker-compose.prod.yml pull web server 拉取本次 SHA 镜像。
  6. 启动数据库与 Redis执行 pnpm --filter server db:deploy
  7. 执行 docker compose --env-file .env.production -f docker-compose.prod.yml up -d --remove-orphans 重启服务。
  8. 通过 /api/v1/health/version 校验运行中的后端版本是否等于本次 commit SHA。

如果最后一步失败Actions 会红掉,说明“代码已合并”不等于“线上容器已更新”。本地或服务器也可以手工运行:

pnpm deploy:check-runtime http://localhost/api/v1/health/version <expected-commit-sha>

Nginx 路由

deploy/nginx/default.conf.template 使用官方 Nginx 镜像的模板机制生成配置:

  • /api/ 转发到 server:3001
  • / 转发到 web:3000
  • X-Forwarded-ProtoX-Forwarded-For 等反向代理头会透传给后端

生产 Compose 默认只监听 HTTP 80。HTTPS 建议优先交给云负载均衡、CDN 或宿主机外层证书管理工具;如果要让本 Compose 内的 Nginx 直接处理 HTTPS可以在后续增加证书 volume 和 443 server block。

数据持久化

生产 Compose 使用三个命名 volume

  • postgres_dataPostgreSQL 数据库,包含业务主数据和 app_data
  • redis_dataRedis AOF 数据。
  • server_dataNestJS 写入的 AI Provider 配置文件,例如 data/ai-config.json

浏览器不再作为业务数据主存储。清浏览器缓存不会删除产品、项目、版本、任务、测试用例、Bug 等业务数据。

AppData 归档与校验V2.5

V2.5 起,已迁移业务 key 的 PUT /api/v1/data/:key 会返回 409 APP_DATA_WRITE_FROZEN,读路径仍保留给历史核对和回滚。停用 AppData 写入前后都建议导出一份只读归档:

pnpm appdata:archive:export -- --out backups/appdata-archive-$(date +%Y%m%d%H%M%S).json
pnpm appdata:archive:verify -- --archive backups/appdata-archive-20260708120000.json

归档 JSON 包含:

  • metadata.appVersion / metadata.appBuildTime / metadata.sourceCommit:导出时的应用版本信息。
  • keys:本次导出的 AppData key 列表。
  • rows[].valueChecksum:每个 key 的 JSON 内容 SHA-256。
  • metadata.payloadChecksum:整份 key list + rows payload 的 SHA-256。

生产环境执行导出前需要确保 DATABASE_URL 指向当前 PostgreSQL。默认输出文件名为 appdata-archive-<timestamp>.json,该模式已加入 .gitignore;真实归档应放入服务器备份目录或对象存储,不提交到代码仓库。

V2.5 一致性校验

完成数据库 migration、AppData 写冻结和归档导出后,建议在发布窗口内运行一致性校验:

pnpm consistency:v25 -- --url http://localhost/api/v1/consistency

本地开发默认检查 http://localhost:3001/api/v1/consistency,也可以不传 --url。校验内容包括 counts、分区键、孤儿引用和审计覆盖

  • error 必须在发布前修复。
  • warn 需要记录原因;历史数据没有审计事件属于预期 warning不阻断 V2.5。
  • 后台页面 /admin/consistency 展示同一份报告,需要当前用户具备 consistency:view

升级流程

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

升级前建议先备份数据库:

docker compose --env-file .env.production -f docker-compose.prod.yml exec postgres pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" > ftb_pm_backup.sql

常见排查

后端是否启动:

curl http://localhost/api/v1/config/ai

数据库是否可用:

docker compose --env-file .env.production -f docker-compose.prod.yml exec postgres pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"

查看日志:

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