# 本地数据库导线上部署文档 这份文档用于把当前本地 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://:@:5432/ 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。