# 部署指南

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

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

## 本地开发部署

```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`。
