Files
website/docs/local-db-to-production-deployment.md
T
2026-04-29 14:23:00 +08:00

234 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 本地数据库导线上部署文档
这份文档用于把当前本地 Payload/Next.js 站点完整搬到线上:代码、PostgreSQL 数据库、`media/` 图片库、`files/` 下载文件、`videos/` 视频文件必须来自同一次导出。
## 1. 上线前原则
- 线上只使用迁移,不使用 schema push。
- 线上启动不自动跑迁移,迁移必须作为单独发布步骤执行。
- 本地导出的数据库和 `media/``files/``videos/` 目录必须成套,不要混用不同时间点的文件。
- 导入线上后不要再跑 seed 脚本,seed/backfill 只应该在本地确认好,再随数据库 dump 一起带上去。当前 seed 默认会保护已有全局内容;只有显式加 `--force` 才会覆盖后台已有配置。
- 如果启动或迁移时出现删除旧表、schema push、交互确认提示,先停止,不要继续确认。
## 2. 线上环境变量
线上 `.env` 至少需要:
```bash
NODE_ENV=production
NEXT_PUBLIC_SITE_URL=https://www.eversolo.com
PAYLOAD_SECRET=<用 openssl rand -base64 48 生成的长随机字符串>
DATABASE_URI=postgres://<user>:<password>@<host>:5432/<database>
PAYLOAD_DB_PUSH=false
PAYLOAD_RUN_MIGRATIONS_ON_START=false
```
说明:
- `PAYLOAD_SECRET` 不能用示例值,也不能和本地随便共用短值。
- `PAYLOAD_DB_PUSH=false` 是为了避免 Payload 用当前 schema 直接改库。
- `PAYLOAD_RUN_MIGRATIONS_ON_START=false` 是为了避免应用启动时弹迁移交互提示,迁移改用 `npm run payload:migrate` 手动执行。
## 3. 本地导出前检查
在本地项目目录执行:
```bash
set -a
source .env
set +a
git status --short
npm run lint
npm run typecheck
npm run build
npm run payload:migrate:status
```
检查本地数据库里不能有 Payload dev schema push 标记:
```bash
psql "$DATABASE_URI" -Atc "select count(*) from payload_migrations where batch = -1;"
```
期望输出是:
```text
0
```
如果不是 `0`,说明这个库还带有开发期 schema push 记录。不要导出这个库去线上,先在本地对齐迁移状态后再导出。
建议再跑一次本地 smoke
```bash
npm run smoke -- http://localhost:3221
```
## 4. 导出本地数据库和上传目录
在本地项目目录执行:
```bash
EXPORT_DIR="release-exports/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$EXPORT_DIR"
pg_dump \
--format=custom \
--no-owner \
--no-acl \
--file="$EXPORT_DIR/eversolo.payload.dump" \
"$DATABASE_URI"
tar -czf "$EXPORT_DIR/eversolo.uploads.tgz" media files videos
shasum -a 256 "$EXPORT_DIR/eversolo.payload.dump" "$EXPORT_DIR/eversolo.uploads.tgz" \
> "$EXPORT_DIR/SHA256SUMS.txt"
```
导出目录里应该有:
```text
eversolo.payload.dump
eversolo.uploads.tgz
SHA256SUMS.txt
```
把整个目录传到服务器,例如:
```bash
rsync -av "$EXPORT_DIR/" deploy@your-server:/srv/eversolo-release/
```
## 5. 线上恢复数据库
在服务器上进入发布目录,先确认校验和:
```bash
cd /srv/eversolo-release
shasum -a 256 -c SHA256SUMS.txt
```
恢复到线上 PostgreSQL。
如果是新空库:
```bash
pg_restore \
--no-owner \
--no-acl \
--dbname "$DATABASE_URI" \
eversolo.payload.dump
```
如果是替换已有测试库或预发布库,并且你已经确认可以清掉旧数据:
```bash
pg_restore \
--clean \
--if-exists \
--no-owner \
--no-acl \
--dbname "$DATABASE_URI" \
eversolo.payload.dump
```
恢复后检查迁移标记:
```bash
psql "$DATABASE_URI" -Atc "select count(*) from payload_migrations where batch = -1;"
npm run payload:migrate:status
```
`batch = -1` 应该是 `0``payload:migrate:status` 应该显示迁移已应用。若代码里有比 dump 更新的迁移,再执行:
```bash
npm run payload:migrate
npm run payload:migrate:status
```
## 6. 线上恢复媒体文件
在服务器应用目录或持久化上传卷目录执行:
```bash
tar -xzf /srv/eversolo-release/eversolo.uploads.tgz -C /srv/eversolo-app/
```
如果线上使用单独的持久化 volume,把解压后的目录同步到 volume:
```bash
rsync -a --delete /srv/eversolo-app/media/ /srv/eversolo-uploads/media/
rsync -a --delete /srv/eversolo-app/files/ /srv/eversolo-uploads/files/
rsync -a --delete /srv/eversolo-app/videos/ /srv/eversolo-uploads/videos/
```
确认应用运行时能从项目根目录或挂载目录访问:
```text
media/
files/
videos/
```
数据库里 media/files/videos 记录只保存文件名和元数据,文件本体必须在对应目录里。
## 7. 构建和启动
在服务器应用目录执行:
```bash
npm ci
npm run typecheck
npm run build
npm run payload:migrate
npm run payload:migrate:status
npm run start
```
如果使用 PM2/systemd/Docker,由进程管理器执行 `npm run start`,但迁移步骤仍然要在启动前单独跑。
健康检查:
```bash
curl -f "$NEXT_PUBLIC_SITE_URL/api/health"
curl -f "$NEXT_PUBLIC_SITE_URL/api/admin/captcha"
npm run smoke -- "$NEXT_PUBLIC_SITE_URL"
```
重点人工打开:
```text
/en
/zh
/en/products/dmp-a10
/en/reviews
/en/reviews?tab=reviews
/en/support
/en/support/tutorial
/en/where-to-buy
/admin
/admin/login
```
后台上线后再手工确认一次:退出登录,打开 `/admin/login`,验证码错误时应该直接失败,验证码正确但密码错误时才进入账号密码校验。
## 8. 回滚
回滚要成套回滚:
1. 切回上一版代码。
2. 恢复上一版数据库 dump。
3. 恢复上一版 `media/``files/`
4. 重新启动并跑 smoke。
线上不要默认执行 down migration 作为回滚方式;生产回滚优先恢复上一套数据快照。
## 9. 禁止操作
- 不要在线上设置 `PAYLOAD_DB_PUSH=true`
- 不要在线上用 `PAYLOAD_MIGRATING=true` 当常规启动方式。
- 不要把数据库 dump 和不同时间点的 `media/``files/``videos/` 混用。
- 不要导入线上后再跑 `npm run seed:import -- --force` 覆盖编辑内容;普通 seed 也只建议在本地验证,不作为线上日常命令。
- 不要在生产已经跑过某个迁移后修改同名迁移文件;需要新建 forward migration。