- 新增只读发布 smoke runner 和 dry-run 测试\n- 将生产部署 workflow 从单点版本检查升级为 smoke test\n- 补充 Docker web runtime 脚本复制、package script 和部署文档\n\nCo-Authored-By: GPT-5 Codex <codex@openai.com>
10 KiB
部署指南
本文档覆盖三种部署方式:
- 本地开发:前端、后端直接用 pnpm 跑,PostgreSQL 和 Redis 用
docker-compose.yml启动。 - 本地服务器部署:一台本机或局域网服务器用
docker-compose.local.yml跑完整 Web、Server、PostgreSQL、Redis、Nginx。 - 云服务器生产:所有服务用
docker-compose.prod.yml编排,Nginx 对外暴露 HTTP,业务数据写入 PostgreSQL volume,AI 配置文件写入 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_datalocal_redis_datalocal_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. 准备配置
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.web、Dockerfile.server、docker-compose.prod.yml、docker-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_USER:SSH 用户。PROD_SSH_KEY:SSH 私钥。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_VERSION、APP_BUILD_TIME、WEB_IMAGE、SERVER_IMAGE 会由 GitHub Actions 在每次发布时自动更新。
之后只要代码合并或 push 到 master,Actions 会自动执行:
- 用当前 commit SHA 构建
web和serverDocker 镜像。 - 推送镜像到 GHCR,镜像 tag 同时包含 commit SHA 和
master。 - SSH 到生产服务器,
git pull --ff-only origin master更新 Compose 和部署脚本。 - 写入
.env.production的APP_VERSION、APP_BUILD_TIME、WEB_IMAGE、SERVER_IMAGE。 - 执行
docker compose --env-file .env.production -f docker-compose.prod.yml pull web server拉取本次 SHA 镜像。 - 启动数据库与 Redis,执行
pnpm --filter server db:deploy。 - 执行
docker compose --env-file .env.production -f docker-compose.prod.yml up -d --remove-orphans重启服务。 - 运行发布 smoke test:校验
/api/v1/health/version、前端首页、产品页、产品 API、V2.2 读路径和 AI 配置端点,并确认运行中的后端版本等于本次 commit SHA。
如果最后一步失败,Actions 会红掉,说明“代码已合并”不等于“线上容器已更新”或关键读路径不可用。本地或服务器也可以手工运行:
pnpm deploy:check-runtime http://localhost/api/v1/health/version <expected-commit-sha>
pnpm deploy:smoke -- --base-url http://localhost --expected-version <expected-commit-sha>
Nginx 路由
deploy/nginx/default.conf.template 使用官方 Nginx 镜像的模板机制生成配置:
/api/转发到server:3001/转发到web:3000X-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 等业务数据。
备份与恢复
备份分两类:PostgreSQL 业务数据和 server_data volume 中的运行时配置。真实备份文件默认写到 backups/,该目录已加入 .gitignore,不要把 dump 或 tar 包提交到仓库。
先演练命令,不写文件:
pnpm backup:postgres -- --dry-run --env-file .env.production
pnpm backup:server-data -- --dry-run --env-file .env.production
执行正式备份:
pnpm backup:postgres -- --env-file .env.production
pnpm backup:server-data -- --env-file .env.production
PostgreSQL 备份使用 pg_dump --format=custom --no-owner --no-acl,便于跨环境恢复。server_data 备份使用只读 volume mount 和 tar -czf,覆盖 AI Provider 配置等后端运行时文件。
恢复数据库必须显式确认覆盖。默认命令会拒绝执行,防止误删现有库:
pnpm restore:postgres -- --env-file .env.production --input backups/postgres/ftb_pm-postgres-20260708T120000Z.dump
确认要把目标数据库重建为 fresh DB 后,再运行:
pnpm restore:postgres -- \
--env-file .env.production \
--input backups/postgres/ftb_pm-postgres-20260708T120000Z.dump \
--confirm-overwrite
恢复前建议先 dry-run 看清将执行的 psql/dropdb/createdb/pg_restore 步骤:
pnpm restore:postgres -- \
--dry-run \
--confirm-overwrite \
--env-file .env.production \
--input backups/postgres/ftb_pm-postgres-20260708T120000Z.dump
如果要恢复到临时库做校验,不覆盖当前生产库:
pnpm restore:postgres -- \
--env-file .env.production \
--input backups/postgres/ftb_pm-postgres-20260708T120000Z.dump \
--target-db ftb_pm_restore_check \
--confirm-overwrite
升级流程
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
升级前建议先备份数据库:
pnpm backup:postgres -- --env-file .env.production
pnpm backup:server-data -- --env-file .env.production
常见排查
后端是否启动:
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
如果前端能打开但数据为空,优先检查:
NEXT_PUBLIC_API_URL是否为/api/v1或正确的完整 API 地址。curl http://localhost/api/v1/config/ai是否返回 200。server日志里是否有 Prisma 或DATABASE_URL错误。- 是否已执行
pnpm --filter server db:deploy。