Files
website/docs/local-db-to-production-deployment.md
T
2026-04-28 09:16:15 +08:00

5.6 KiB
Raw Blame History

本地数据库导线上部署文档

这份文档用于把当前本地 Payload/Next.js 站点完整搬到线上:代码、PostgreSQL 数据库、media/ 图片库、files/ 下载文件必须来自同一次导出。

1. 上线前原则

  • 线上只使用迁移,不使用 schema push。
  • 线上启动不自动跑迁移,迁移必须作为单独发布步骤执行。
  • 本地导出的数据库和 media/files/ 目录必须成套,不要混用不同时间点的文件。
  • 导入线上后不要再跑 seed 脚本,seed/backfill 只应该在本地确认好,再随数据库 dump 一起带上去。
  • 如果启动或迁移时出现删除旧表、schema push、交互确认提示,先停止,不要继续确认。

2. 线上环境变量

线上 .env 至少需要:

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. 本地导出前检查

在本地项目目录执行:

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 标记:

psql "$DATABASE_URI" -Atc "select count(*) from payload_migrations where batch = -1;"

期望输出是:

0

如果不是 0,说明这个库还带有开发期 schema push 记录。不要导出这个库去线上,先在本地对齐迁移状态后再导出。

建议再跑一次本地 smoke

npm run smoke -- http://localhost:3221

4. 导出本地数据库和上传目录

在本地项目目录执行:

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

shasum -a 256 "$EXPORT_DIR/eversolo.payload.dump" "$EXPORT_DIR/eversolo.uploads.tgz" \
  > "$EXPORT_DIR/SHA256SUMS.txt"

导出目录里应该有:

eversolo.payload.dump
eversolo.uploads.tgz
SHA256SUMS.txt

把整个目录传到服务器,例如:

rsync -av "$EXPORT_DIR/" deploy@your-server:/srv/eversolo-release/

5. 线上恢复数据库

在服务器上进入发布目录,先确认校验和:

cd /srv/eversolo-release
shasum -a 256 -c SHA256SUMS.txt

恢复到线上 PostgreSQL。

如果是新空库:

pg_restore \
  --no-owner \
  --no-acl \
  --dbname "$DATABASE_URI" \
  eversolo.payload.dump

如果是替换已有测试库或预发布库,并且你已经确认可以清掉旧数据:

pg_restore \
  --clean \
  --if-exists \
  --no-owner \
  --no-acl \
  --dbname "$DATABASE_URI" \
  eversolo.payload.dump

恢复后检查迁移标记:

psql "$DATABASE_URI" -Atc "select count(*) from payload_migrations where batch = -1;"
npm run payload:migrate:status

batch = -1 应该是 0payload:migrate:status 应该显示迁移已应用。若代码里有比 dump 更新的迁移,再执行:

npm run payload:migrate
npm run payload:migrate:status

6. 线上恢复媒体文件

在服务器应用目录或持久化上传卷目录执行:

tar -xzf /srv/eversolo-release/eversolo.uploads.tgz -C /srv/eversolo-app/

如果线上使用单独的持久化 volume,把解压后的目录同步到 volume:

rsync -a --delete /srv/eversolo-app/media/ /srv/eversolo-uploads/media/
rsync -a --delete /srv/eversolo-app/files/ /srv/eversolo-uploads/files/

确认应用运行时能从项目根目录或挂载目录访问:

media/
files/

数据库里 media/files 记录只保存文件名和元数据,文件本体必须在对应目录里。

7. 构建和启动

在服务器应用目录执行:

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,但迁移步骤仍然要在启动前单独跑。

健康检查:

curl -f "$NEXT_PUBLIC_SITE_URL/api/health"
curl -f "$NEXT_PUBLIC_SITE_URL/api/admin/captcha"
npm run smoke -- "$NEXT_PUBLIC_SITE_URL"

重点人工打开:

/en
/zh
/en/products/dmp-a10
/en/reviews
/en/reviews?tab=reviews
/en/support
/en/support/tutorial
/en/dealers
/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/ 混用。
  • 不要导入线上后再跑 npm run seed:import 覆盖编辑内容。
  • 不要在生产已经跑过某个迁移后修改同名迁移文件;需要新建 forward migration。