docs(deploy): 修正多入口单部署方案
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
# Multi-Address Single Deployment Data Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Ensure external and local/LAN access addresses are documented and verified as multiple entrypoints to the same deployment stack and database, not two separately running data sets.
|
||||
|
||||
**Architecture:** The application keeps one active Compose stack for formal business data. External and local addresses both route to that stack's Nginx, which forwards `/api/` to the same NestJS server and PostgreSQL volume. `docker-compose.local.yml` remains an independent local/LAN demo stack and must not be described as a synced copy of production data.
|
||||
|
||||
**Tech Stack:** Docker Compose, Nginx reverse proxy template, Next.js same-origin API config, Node deployment verifier, Markdown deployment docs.
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
- Modify `scripts/verify-production-deploy.mjs`: add checks that deployment docs and env examples describe multi-address single-stack behavior.
|
||||
- Modify `.env.production.example`: add comments that `SERVER_NAME` is the primary public host and local/LAN access must route to the same Nginx stack.
|
||||
- Modify `.env.local-server.example`: add comments that this is an independent local/LAN demo stack, not a synced view of production data.
|
||||
- Modify `docs/deployment.md`: explain the recommended multi-address single deployment and warn against running prod/local stacks for the same business.
|
||||
- Modify `docs/architecture.md`: document that one formal business stack may have multiple access addresses.
|
||||
- Modify `docs/decisions.md`: add a decision that address-level consistency is solved by one active deployment stack, not data sync.
|
||||
- Modify `docs/workflow.md`: update deployment flow and troubleshooting checks for address routing.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Add Deployment Verifier Expectations
|
||||
|
||||
**Files:**
|
||||
- Modify: `scripts/verify-production-deploy.mjs`
|
||||
|
||||
- [ ] **Step 1: Add failing verifier snippets**
|
||||
|
||||
In `scripts/verify-production-deploy.mjs`, update existing checks so the deployment verifier requires the new wording.
|
||||
|
||||
Add these snippets to the `.env.production.example` check:
|
||||
|
||||
```js
|
||||
'Primary public host',
|
||||
'same Compose Nginx',
|
||||
```
|
||||
|
||||
Add these snippets to the `.env.local-server.example` check:
|
||||
|
||||
```js
|
||||
'independent local/LAN demo stack',
|
||||
'does not sync with production data',
|
||||
```
|
||||
|
||||
Add these snippets to the `docs/deployment.md` check:
|
||||
|
||||
```js
|
||||
'同一部署多入口访问',
|
||||
'外网地址和本地地址',
|
||||
'同一套 Compose',
|
||||
'不要同时启动',
|
||||
```
|
||||
|
||||
Add these snippets to the `docker-compose.prod.yml` check:
|
||||
|
||||
```js
|
||||
'SERVER_NAME',
|
||||
'NEXT_PUBLIC_API_URL',
|
||||
```
|
||||
|
||||
Keep all existing checks that still apply.
|
||||
|
||||
- [ ] **Step 2: Run verifier to confirm it fails**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
pnpm deploy:verify
|
||||
```
|
||||
|
||||
Expected: command exits non-zero and prints missing snippets for `.env.production.example`, `.env.local-server.example`, and `docs/deployment.md`.
|
||||
|
||||
- [ ] **Step 3: Commit failing verifier**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
git add scripts/verify-production-deploy.mjs
|
||||
git commit -m "test(deploy): 覆盖多入口单部署校验"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Clarify Environment Examples
|
||||
|
||||
**Files:**
|
||||
- Modify: `.env.production.example`
|
||||
- Modify: `.env.local-server.example`
|
||||
|
||||
- [ ] **Step 1: Update production env comments**
|
||||
|
||||
In `.env.production.example`, replace:
|
||||
|
||||
```env
|
||||
# Public entrypoint
|
||||
SERVER_NAME=pm.example.com
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```env
|
||||
# Public and local entrypoints
|
||||
# Primary public host. Local/LAN addresses should route to the same Compose Nginx stack,
|
||||
# not to a separate docker-compose.local.yml stack, when they need the same business data.
|
||||
SERVER_NAME=pm.example.com
|
||||
```
|
||||
|
||||
Keep `NEXT_PUBLIC_API_URL=/api/v1`.
|
||||
|
||||
- [ ] **Step 2: Update local-server env comments**
|
||||
|
||||
In `.env.local-server.example`, replace:
|
||||
|
||||
```env
|
||||
# Copy to .env.local-server for an all-in-one local/LAN deployment.
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```env
|
||||
# Copy to .env.local-server for an independent local/LAN demo stack.
|
||||
# This stack uses local_* volumes and does not sync with production data.
|
||||
# If external and local addresses must show the same business data, route both addresses to the same production Compose stack instead.
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Run verifier to confirm docs still fail**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
pnpm deploy:verify
|
||||
```
|
||||
|
||||
Expected: command still exits non-zero because `docs/deployment.md` has not yet been updated.
|
||||
|
||||
- [ ] **Step 4: Commit env comments**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
git add .env.production.example .env.local-server.example
|
||||
git commit -m "docs(deploy): 标注本地栈不与生产数据同步"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Update Deployment And Architecture Docs
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/deployment.md`
|
||||
- Modify: `docs/architecture.md`
|
||||
- Modify: `docs/decisions.md`
|
||||
- Modify: `docs/workflow.md`
|
||||
|
||||
- [ ] **Step 1: Add deployment section for multi-address access**
|
||||
|
||||
In `docs/deployment.md`, add this section before “本地服务器部署”:
|
||||
|
||||
````markdown
|
||||
## 同一部署多入口访问
|
||||
|
||||
如果只是希望外网地址和本地地址看到同一份业务数据,不要启动两套部署栈。正确方式是让外网域名、公网 IP、内网 IP 或本机地址都进入同一套 Compose 的 Nginx。
|
||||
|
||||
```text
|
||||
外网地址和本地地址
|
||||
-> 同一套 Compose Nginx
|
||||
-> 同一个 web/server
|
||||
-> 同一个 PostgreSQL volume
|
||||
```
|
||||
|
||||
生产同域部署保持:
|
||||
|
||||
```env
|
||||
NEXT_PUBLIC_API_URL=/api/v1
|
||||
```
|
||||
|
||||
这样浏览器从哪个地址打开页面,就请求该地址下的 `/api/v1`。只要这些地址最终进入同一个 Nginx/server,数据就是同一份。
|
||||
|
||||
不要同时启动 `docker-compose.prod.yml` 和 `docker-compose.local.yml` 来承载同一套正式业务。它们使用不同 volume,会看到两套数据。
|
||||
````
|
||||
|
||||
Use the four-backtick outer fence shown above if copying this plan into another Markdown document, because the section contains nested fences.
|
||||
|
||||
- [ ] **Step 2: Clarify local-server deployment is independent**
|
||||
|
||||
In `docs/deployment.md`, under “本地服务器部署”, add this paragraph near the top:
|
||||
|
||||
```markdown
|
||||
本地服务器部署是一套独立 local/LAN 演示栈,使用 `local_*` volumes。它适合办公室内网试用或离线演示,不会与云服务器生产数据自动保持一致。如果目标是外网地址和本地地址看到同一份正式业务数据,请使用上面的“同一部署多入口访问”,而不是同时运行两套栈。
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Update architecture production boundary**
|
||||
|
||||
In `docs/architecture.md`, under the production deployment layer, add:
|
||||
|
||||
```markdown
|
||||
同一套正式业务部署可以有多个访问入口,例如外网域名、公网 IP、内网 IP 或本机地址。多入口必须进入同一个 Nginx/server/PostgreSQL 栈,才能看到同一份数据。`docker-compose.local.yml` 是独立本地/LAN 演示栈,不能作为生产栈的数据同步副本。
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Add decision record**
|
||||
|
||||
In `docs/decisions.md`, append a new decision:
|
||||
|
||||
```markdown
|
||||
## 40. 外网与本地访问地址通过同一部署栈保持数据一致
|
||||
|
||||
**问题**:用户希望外网地址和本地/内网地址访问系统时看到同一份业务数据。如果两个地址分别打到 `docker-compose.prod.yml` 和 `docker-compose.local.yml`,就会使用不同 PostgreSQL volume,数据天然分叉。
|
||||
|
||||
**决策**:外网地址和本地地址应作为同一套正式业务部署的多个入口,全部路由到同一个 Nginx/server/PostgreSQL 栈。`docker-compose.local.yml` 只用于独立本地/LAN 演示,不承诺与生产数据一致。
|
||||
|
||||
**理由**:这是访问入口问题,不是数据同步问题。保持单部署栈可以复用现有 `/api/v1` 同域配置和 `app_data` 乐观锁,避免引入双向同步、冲突合并和数据库复制复杂度。
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Update workflow deployment flow**
|
||||
|
||||
In `docs/workflow.md`, in the production deployment flow, add:
|
||||
|
||||
```markdown
|
||||
外网地址和本地地址要看到同一份数据时,必须让两个地址都进入同一套 Compose/Nginx。不要同时用 `docker-compose.prod.yml` 和 `docker-compose.local.yml` 承载同一套业务;本地栈使用 `local_*` volumes,只适合独立演示。
|
||||
```
|
||||
|
||||
Also add this troubleshooting item:
|
||||
|
||||
```markdown
|
||||
如果外网地址和本地地址数据不一致,先检查两个地址是否打到了同一个 `/api/v1/config/ai` 后端和同一个 Compose project;不要先做数据库同步。
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Run verifier and type checks**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
pnpm deploy:verify
|
||||
pnpm --filter web type-check
|
||||
pnpm --filter server type-check
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `pnpm deploy:verify` prints `Production deployment artifacts verified.`
|
||||
- Both type-check commands exit 0.
|
||||
|
||||
- [ ] **Step 7: Commit docs**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
git add docs/deployment.md docs/architecture.md docs/decisions.md docs/workflow.md
|
||||
git commit -m "docs(deploy): 说明多入口访问同一部署数据"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Final Verification And Reporting
|
||||
|
||||
**Files:**
|
||||
- No file changes expected.
|
||||
|
||||
- [ ] **Step 1: Run final verification**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
pnpm deploy:verify
|
||||
pnpm --filter web type-check
|
||||
pnpm --filter server type-check
|
||||
git status --short
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `pnpm deploy:verify` exits 0.
|
||||
- `pnpm --filter web type-check` exits 0.
|
||||
- `pnpm --filter server type-check` exits 0.
|
||||
- `git status --short` shows only intentional plan/spec files if they were not committed, otherwise no output.
|
||||
|
||||
- [ ] **Step 2: Report operational guidance**
|
||||
|
||||
In the final response, include:
|
||||
|
||||
```text
|
||||
外网地址和本地地址要看同一份数据时,只运行一套正式业务 Compose;让所有地址都反代到同一个 Nginx/server/PostgreSQL。
|
||||
```
|
||||
|
||||
Also include:
|
||||
|
||||
```text
|
||||
docker-compose.local.yml 是独立演示栈;如果同时和生产栈运行,会看到两套数据。
|
||||
```
|
||||
@@ -1,143 +1,139 @@
|
||||
# 本地服务器与云服务器单主数据源设计
|
||||
# 外网与本地访问地址共享同一数据设计
|
||||
|
||||
## 背景
|
||||
|
||||
当前生产部署使用 `docker-compose.prod.yml`,云服务器的数据写入 `postgres_data`、`redis_data`、`server_data` 三个 volume。本地服务器部署使用 `docker-compose.local.yml`,数据写入 `local_postgres_data`、`local_redis_data`、`local_server_data` 三个独立 volume。
|
||||
用户澄清后的真实问题不是“两台服务器之间同步数据”,而是:同一套项目系统通过外网地址访问、通过本地/内网地址访问时,应该看到同一份业务数据。
|
||||
|
||||
这意味着本地服务器和云服务器默认是两套数据。本地服务器新增或修改产品、项目、版本、任务、测试用例、Bug 后,云服务器不会自动更新。
|
||||
当前仓库同时提供:
|
||||
|
||||
用户确认本地和云端都会做备份,因此在线业务不需要两套独立主库。备份用于灾备,在线写入源应保持唯一。
|
||||
- `docker-compose.prod.yml`:云服务器生产栈,使用 `postgres_data`、`redis_data`、`server_data`。
|
||||
- `docker-compose.local.yml`:本地服务器/LAN 栈,使用 `local_postgres_data`、`local_redis_data`、`local_server_data`。
|
||||
|
||||
如果为了同一套业务同时启动这两套栈,外网地址和本地地址很可能分别打到不同的 Compose project、不同的 PostgreSQL volume,因此会看到两套数据。
|
||||
|
||||
## 目标
|
||||
|
||||
- 云服务器 PostgreSQL 作为唯一业务主数据源。
|
||||
- 本地服务器访问和修改的业务数据与云服务器一致。
|
||||
- 本地服务器上的写入立即落到云端主库,云端打开后能看到同一份数据。
|
||||
- 保留本地服务器备份能力,但默认不把本地 PostgreSQL 当作业务写入库。
|
||||
- 避免双主同步、定时合并、手工覆盖等高风险机制。
|
||||
- 外网访问地址和本地/内网访问地址进入同一套运行中的服务栈。
|
||||
- 同一套服务栈只使用一个 PostgreSQL 主数据 volume。
|
||||
- 用户从任意入口创建或修改产品、项目、版本、任务、测试用例、Bug 后,从另一个入口刷新能看到相同数据。
|
||||
- 文档明确区分“同一套系统的多个访问入口”和“独立本地演示环境”。
|
||||
- 避免把这个需求误实现为双向同步或跨服务器数据库复制。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不做本地数据库和云端数据库的双向同步。
|
||||
- 不支持离线写入后再自动合并到云端。
|
||||
- 不把云端 PostgreSQL 裸露到公网。
|
||||
- 不在本次改动中迁移 AI Provider 配置文件到数据库。
|
||||
- 不要求本地服务器连接云服务器数据库。
|
||||
- 不迁移 AI Provider 配置文件到数据库。
|
||||
- 不引入后台同步任务、冲突合并队列或数据库复制方案。
|
||||
|
||||
## 推荐方案
|
||||
|
||||
采用“云端单主库 + 本地服务器连接云端主库”的模式。
|
||||
采用“单部署栈,多访问入口”的模式。
|
||||
|
||||
本地服务器仍可运行 `web`、`server`、`redis`、`nginx`,但 `server` 的 `DATABASE_URL` 指向云端主库。业务数据通过 NestJS `DataModule` 写入云端 PostgreSQL 的 `app_data` 表。前端仍走同域 `/api/v1`,由本地 Nginx 转发到本地 server;本地 server 再连接云端数据库。
|
||||
无论用户从外网域名、服务器公网 IP、局域网 IP,还是本机地址访问,都应该进入同一个 Nginx,然后由该 Nginx 转发到同一个 `web` 和 `server`,最终读写同一个 PostgreSQL。
|
||||
|
||||
```text
|
||||
本地浏览器
|
||||
-> 本地 Nginx /api
|
||||
-> 本地 NestJS server
|
||||
-> 云端 PostgreSQL 主库
|
||||
外网地址 / 域名
|
||||
-> 同一个 Nginx
|
||||
-> 同一个 NestJS server
|
||||
-> 同一个 PostgreSQL volume
|
||||
|
||||
云端浏览器
|
||||
-> 云端 Nginx /api
|
||||
-> 云端 NestJS server
|
||||
-> 云端 PostgreSQL 主库
|
||||
本地 / 内网地址
|
||||
-> 同一个 Nginx
|
||||
-> 同一个 NestJS server
|
||||
-> 同一个 PostgreSQL volume
|
||||
```
|
||||
|
||||
## 部署配置设计
|
||||
前端继续使用同域 API:
|
||||
|
||||
### 1. 新增本地共享主库 env 示例
|
||||
|
||||
新增 `.env.local-server.cloud-data.example`,用于说明本地服务器连接云端主库时应填写的配置。
|
||||
|
||||
关键字段:
|
||||
|
||||
- `DATABASE_URL`:云端 PostgreSQL 连接串,推荐通过 VPN、专线、内网穿透或 SSH tunnel 暴露给本地服务器。
|
||||
- `NEXT_PUBLIC_API_URL=/api/v1`:本地浏览器仍访问本地 Nginx。
|
||||
- `NEXTAUTH_URL`:本地服务器访问地址,例如 `http://192.168.1.50:8080`。
|
||||
- `REDIS_URL=redis://redis:6379`:Redis 可继续本地运行,当前业务主数据不依赖 Redis 持久化同步。
|
||||
|
||||
### 2. 调整本地 Compose 的数据库依赖
|
||||
|
||||
`docker-compose.local.yml` 当前强制启动并依赖本地 `postgres`。这会让本地部署天然变成另一套业务数据。
|
||||
|
||||
调整后:
|
||||
|
||||
- `postgres` 改为可选 profile,例如 `profiles: ['local-db']`。
|
||||
- `server.depends_on` 不再强依赖 `postgres`,只保留对 `redis` 的健康依赖。
|
||||
- 默认本地服务器部署要求显式提供 `DATABASE_URL`。
|
||||
- 如果确实要跑完全离线的本地演示库,可以通过 profile 启动本地 Postgres。
|
||||
|
||||
预期命令:
|
||||
|
||||
```bash
|
||||
# 本地服务器连接云端主库
|
||||
docker compose --env-file .env.local-server.cloud-data -f docker-compose.local.yml up -d
|
||||
|
||||
# 完全本地演示库
|
||||
docker compose --env-file .env.local-server -f docker-compose.local.yml --profile local-db up -d
|
||||
```env
|
||||
NEXT_PUBLIC_API_URL=/api/v1
|
||||
```
|
||||
|
||||
### 3. 更新部署文档
|
||||
这样浏览器从哪个地址打开页面,就向该地址下的 `/api/v1` 发请求。只要这些地址最终落到同一套 Nginx/server,数据天然一致。
|
||||
|
||||
`docs/deployment.md` 增加“本地服务器连接云端主库”章节,明确:
|
||||
## 部署模式
|
||||
|
||||
- 推荐模式是云端单主库。
|
||||
- 本地服务器默认不应使用独立业务库。
|
||||
- 本地和云端备份是灾备,不是双主同步。
|
||||
- 云端数据库连接必须走安全通道。
|
||||
### 1. 生产/正式业务栈
|
||||
|
||||
`docs/architecture.md` 更新生产部署边界,说明本地服务器可作为云端主库的第二个应用入口。
|
||||
正式业务只运行一套 Compose,例如云服务器上运行 `docker-compose.prod.yml`。
|
||||
|
||||
`docs/decisions.md` 增加设计决策:在线业务数据采用单主数据源,不做双主同步。
|
||||
该栈可以同时支持:
|
||||
|
||||
`docs/workflow.md` 更新部署流程,避免用户把本地服务器误当成独立生产库。
|
||||
- 外网域名:`https://pm.example.com`
|
||||
- 公网 IP:`http://x.x.x.x`
|
||||
- 内网 IP:`http://192.168.1.50`
|
||||
- 本机访问:`http://localhost`
|
||||
|
||||
## 安全边界
|
||||
这些访问方式只要都进入同一个 Nginx,就会共享同一份数据。
|
||||
|
||||
推荐连接方式按优先级排序:
|
||||
### 2. 本地/LAN 演示栈
|
||||
|
||||
1. VPN 或组网工具,使本地服务器通过私网访问云端数据库。
|
||||
2. SSH tunnel,只在本地服务器和云服务器之间建立转发。
|
||||
3. 云安全组只允许本地服务器固定公网 IP 访问数据库端口。
|
||||
`docker-compose.local.yml` 只能用于一套独立的本地/LAN 演示环境。它默认使用 `local_*` volumes,不会和生产栈共享数据。
|
||||
|
||||
不推荐:
|
||||
文档必须明确:如果用户希望外网地址和本地地址看到同一份正式业务数据,不要同时运行 local 栈和 prod 栈来承载同一套业务。
|
||||
|
||||
- PostgreSQL `5432` 对公网开放给任意来源。
|
||||
- 多台服务器共享同一个弱密码数据库账户。
|
||||
- 在 Git 中提交真实 `DATABASE_URL`、数据库密码或 AI Key。
|
||||
## 配置设计
|
||||
|
||||
## 备份策略
|
||||
### Nginx
|
||||
|
||||
备份保留两地:
|
||||
当前 `deploy/nginx/default.conf.template` 只有一个 `server` block,并使用:
|
||||
|
||||
- 云端定期备份主库。
|
||||
- 本地定期拉取云端主库备份或保存导出的快照。
|
||||
```nginx
|
||||
server_name ${SERVER_NAME};
|
||||
```
|
||||
|
||||
备份文件不参与实时业务写入。发生故障时由人工选择某个备份恢复为新的主库,恢复前先停止其他写入入口,避免恢复期间出现新的分叉。
|
||||
因为同一个 Nginx 容器只有这一套 80 端口 server block,即使 Host 不匹配,Nginx 也会把请求落到该默认 server block。因此外网域名和内网 IP 在多数单站点部署中已经可以进入同一套服务。
|
||||
|
||||
## 数据一致性与冲突
|
||||
文档需要补充:
|
||||
|
||||
因为只有云端 PostgreSQL 是主库,本地和云端不会出现数据库级双写冲突。
|
||||
- `SERVER_NAME` 可以保留主域名。
|
||||
- 如果服务器上存在外层 Nginx、多站点配置或严格 host 路由,需要把外网域名和内网访问名都转发到同一套 Compose Nginx。
|
||||
- 不要为外网和本地访问分别启动两套 Compose。
|
||||
|
||||
应用层仍保留现有 `app_data` 乐观锁:
|
||||
### 前端 API
|
||||
|
||||
- 多个用户同时修改同一个业务文档时,后端返回 `409 APP_DATA_CONFLICT`。
|
||||
- 前端不自动覆盖服务端新版本。
|
||||
`NEXT_PUBLIC_API_URL` 应保持:
|
||||
|
||||
该机制继续处理多人同时编辑,而不是处理两套数据库同步。
|
||||
```env
|
||||
NEXT_PUBLIC_API_URL=/api/v1
|
||||
```
|
||||
|
||||
不要为外网和本地访问分别写成不同绝对 API 地址。绝对地址可能让不同入口打到不同后端,重新制造数据分叉。
|
||||
|
||||
### NextAuth URL
|
||||
|
||||
`NEXTAUTH_URL` 继续使用主要正式访问地址。当前系统的业务数据读写不依赖浏览器 localStorage 作为主存储;数据一致性的关键是 `/api/v1` 是否落到同一个后端和数据库。
|
||||
|
||||
如果后续接入 OAuth 回调,需要再评估多 Host 登录体验,但这不影响本次业务数据一致性设计。
|
||||
|
||||
## 文档与脚本调整
|
||||
|
||||
需要更新:
|
||||
|
||||
- `docs/deployment.md`:新增“同一部署多入口访问”说明;强调外网/内网要进入同一套 Compose。
|
||||
- `docs/architecture.md`:生产部署边界改为“一个正式业务栈可以有多个访问入口”。
|
||||
- `docs/decisions.md`:增加决策,外网/本地地址一致性通过同一部署栈保证,不做数据同步。
|
||||
- `docs/workflow.md`:部署流程提示不要为同一业务同时启动 prod 和 local 两套栈。
|
||||
- `.env.production.example`:注释说明 `SERVER_NAME` 是主要域名,内网 IP 通常也会命中同一 Nginx;多站点环境需显式路由。
|
||||
- `.env.local-server.example`:注释说明该文件用于独立本地/LAN 演示库,不会与生产数据一致。
|
||||
- `scripts/verify-production-deploy.mjs`:增加部署文档关键语句校验,避免后续文档丢失这个约束。
|
||||
|
||||
## 验证方式
|
||||
|
||||
完成实现后需要验证:
|
||||
实现后需要验证:
|
||||
|
||||
1. 本地服务器启动后,`curl http://localhost:8080/api/v1/config/ai` 返回 200。
|
||||
2. 本地服务器创建一条业务数据,例如产品或任务。
|
||||
3. 云服务器页面刷新后能看到同一条数据。
|
||||
4. 云服务器修改同一条数据后,本地服务器刷新能看到变化。
|
||||
5. 停止本地 `postgres` 容器后,本地服务器仍能读写业务数据。
|
||||
6. `pnpm deploy:verify` 通过。
|
||||
7. 前端和后端类型检查通过。
|
||||
1. `pnpm deploy:verify` 通过。
|
||||
2. `pnpm --filter web type-check` 通过。
|
||||
3. `pnpm --filter server type-check` 通过。
|
||||
4. 正式栈启动后,外网地址访问 `/api/v1/config/ai` 返回 200。
|
||||
5. 同一台服务器的本地/内网地址访问 `/api/v1/config/ai` 返回 200。
|
||||
6. 从外网地址创建一条业务数据后,从本地/内网地址刷新能看到。
|
||||
7. 从本地/内网地址修改同一条业务数据后,从外网地址刷新能看到。
|
||||
|
||||
## 风险与处理
|
||||
|
||||
- 云端主库不可达时,本地服务器不能写业务数据。这是单主设计的预期行为,错误信息应通过现有 API 失败提示暴露。
|
||||
- 如果本地仍误启独立 Postgres 且 `DATABASE_URL` 指向它,会再次形成两套数据。文档和 env 示例必须把默认推荐改成云端主库。
|
||||
- AI Provider 配置当前仍是 server volume 文件。本地和云端 AI 配置可能不一致;这是本次非目标。后续如果需要,也应把 AI 配置迁入数据库或明确只在云端维护。
|
||||
- 如果外网地址和本地地址分别指向不同 Compose project,数据仍会分叉。处理方式是停止其中一套业务栈,只保留一个正式业务栈。
|
||||
- 如果 `NEXT_PUBLIC_API_URL` 被配置成绝对 URL,不同入口可能绕到不同后端。处理方式是正式同域部署保持 `/api/v1`。
|
||||
- 如果机器上还有外层 Nginx 或宝塔面板,多 Host 需要全部反代到同一套 Compose Nginx。
|
||||
- 本地/LAN 演示栈仍然有价值,但它是独立演示环境,不承诺与正式业务数据一致。
|
||||
|
||||
Reference in New Issue
Block a user