生成日期:2026-08-02
系统版本:V1.0.0
数据库:PostgreSQL 18(库名
mai_2_dingxin)交付包:
mai-2-dingxin_deploy_pkg_20260802.tar.gz
一、本交付包包含的内容(必须打包)
1. 应用源码与构建配置
文件/目录 | 说明 | 约体积 |
|---|---|---|
| 应用源码(Next.js 16 + TS + Tailwind 4 + next-intl 中英双语) | 1.6M |
| 静态资源(图片/字体;含后台登录页 M2-Logo) | 4.2M |
| 运维脚本(如 set-template.mjs) | 196K |
| 依赖与可复现锁版本 | — |
| 构建与类型配置 | — |
| ⚠️ 运行环境变量(含 | — |
| 环境变量模板(参考,无密钥) | — |
2. 用户数据(不可重建,必须整体迁移)
文件/目录 | 说明 |
|---|---|
| 后台上传的图片/文件(5.3M,39 个);迁移时必须原样复制到目标机相同相对路径 |
| PostgreSQL 自定义格式( |
| gzip 压缩纯文本 SQL,可读、通用 |
3. 部署与文档(建议随包,便于部署)
Dockerfile/docker-compose.yml/.dockerignore— 容器化部署ecosystem.config.js— PM2 进程管理deploy-nginx.conf/deploy/nginx-cache.conf— Nginx 反向代理配置DEPLOY.md、部署运行手册.md、宝塔面板部署手册-非Docker.md、飞牛NAS部署指南.md、docs/module-charter.md— 各部署场景文档README.md/CHANGELOG.md/LICENSE/AGENTS.md/CLAUDE.md— 项目说明seed-import.sql— 由旧 sql.js 生成的种子数据(可选;全新库初始化用,完整业务数据请用_db_backup)本说明文档
二、没有打包的文件(没有必要,原因)
文件/目录 | 体积 | 为什么不打包 |
|---|---|---|
| ~666M | 依赖,目标机 |
| ~34M | Next.js 构建产物, |
| ~0.5M | 已弃用的 sql.js 单文件库残留;数据已迁至 PostgreSQL(见 |
| — | 旧备份,冗余 |
| ~15M | 模板删除时的临时备份,已无用 |
| 大 | PostgreSQL 二进制 + pgdata,体积大且环境相关;目标机重装 PG 后恢复 |
| ~490M | 历史归档副本 |
| — | 测试覆盖率与测试代码,非运行必须 |
| ~0.4M | 项目记忆(本机 AI 助手上下文),非运行必须,可单独备份 |
| — | 原始静态 Bootstrap 模板目录,对应模板已删除,系统不再依赖 |
| — | 与部署无关,且可能含敏感信息 |
| — | 运行日志 |
注:
.gitignore已约定/data/不入库、.env不入库——印证数据库与上传文件应单独迁移,而非随源码版本管理。
三、恢复 / 部署步骤(详细)
下面按「裸机/云服务器(launcher 或 PM2)」与「Docker」两条路线给出可执行细节。无论哪种,数据库都是 PostgreSQL(不是 sqlite)且必须单独准备并恢复,代码包里不含数据库文件。
0. 前置要求
目标机 Node.js ≥ 22(本机验证 22.22;建议 22 LTS)。
目标机 PostgreSQL ≥ 18:本备份由 PG 18.4 生成,
pg_restore不能恢复到更低版本。若走 Docker,需把docker-compose.yml里的postgres:16-alpine改为postgres:18-alpine,否则恢复会报版本不兼容。准备两个强随机值(用
openssl rand -base64 48生成):ADMIN_JWT_SECRET、SECRET_MASTER_KEY。
1. 解压
部署包文件名为
mai-2-dingxin_deploy_pkg_20260802.tar.gz(约 9.5 MB,已验证可正常解开为 299 个文件)。
Linux / 云服务器(推荐,标准流程)
cd /path/to/package # 进入部署包所在目录(mai-2-dingxin_deploy_pkg_20260802.tar.gz 必须在此)
mkdir -p /opt/mai-2-dingxin
tar -xzf mai-2-dingxin_deploy_pkg_20260802.tar.gz -C /opt/mai-2-dingxin
cd /opt/mai-2-dingxinWindows(Git Bash / WSL 终端)
# ⚠️ 坑:Git Bash 的 tar 会把 "C:/..." 当成远程主机,报 "Cannot connect to C: resolve failed"
# 必须改用 /c/... 形式(或先把终端 cd 到包所在目录再用相对名)
mkdir -p /c/opt/mai-2-dingxin
tar -xzf /c/Users/<你>/mai-2-dingxin_deploy_pkg_20260802.tar.gz -C /c/opt/mai-2-dingxin
cd /c/opt/mai-2-dingxinPowerShell 原生
tar.exe支持C:/...形式;若用 PowerShell 可不用改路径。
解压后顶层应包含:src/ public/ scripts/ data/ _db_backup/ .env.local package.json ... 等(详见第二节「必须打包」清单)。
2. 安装依赖
npm install # 或 npm ci(包内含 package-lock.json,可复现)
.env.local已随包提供(含DATABASE_URL与各项密钥)。迁移到新机器后,请立即把其中的DATABASE_URL、密码、ADMIN_JWT_SECRET、SECRET_MASTER_KEY改为新环境的强值,并与代码/数据库备份分开保管。
3. 准备 PostgreSQL 与空库
方式 A — 独立安装 PostgreSQL(生产推荐)
createdb mai_2_dingxin # 以 postgres 超级用户执行;或修改 .env.local 的 DATABASE_URL 指向已存在的库方式 B — 复用嵌入式沙箱(开发/内网,与当前本机一致)
npm i @embedded-postgres/windows-x64 # 仅服务端
# 用 _pg-sandbox/pgclient/bin 下的 psql / pg_dump / pg_restore 客户端
# 启动 PG 后建库 mai_2_dingxin确保 .env.local 的 DATABASE_URL 能连通该库(如 postgresql://user:pass@127.0.0.1:5432/mai_2_dingxin)。
4. 恢复数据(任选其一,目标库需已建好)
若库非空,加 --clean --if-exists 先清理再恢复。
方式一(推荐,
-Fc自定义格式,支持单表-t与并行-j):bash export PATH="/path/to/pgclient/bin:$PATH" # 仅沙箱需设置;或设 PG_BIN_DIR 指向客户端目录 pg_restore -Fc --clean --if-exists -d mai_2_dingxin _db_backup/mai_2_dingxin_20260802.dump方式二(纯文本 SQL):
bash gunzip -c _db_backup/mai_2_dingxin_20260802.sql.gz | psql -d mai_2_dingxin校验:恢复后
psql -d mai_2_dingxin -c "\dt"应看到data、messages两张表;data表应有约 12 行 KV(about/cases/categories/company/homepage/navigation/news/products/settings/solutions/users/jobs)。
5. 复制用户上传文件
包内已含 data/uploads/,解压即到位。若单独迁移,务必原样复制到 <项目根>/data/uploads/(Docker 下该目录被 ./data 挂载卷覆盖,同样需存在)。
上传图片由文件系统存储、数据库只存路径;漏复制会导致前台/后台图片 404。
6. 构建
NODE_OPTIONS= npm run build # 必须清空 NODE_OPTIONS,否则沙箱 --use-system-ca 会被 Turbopack Worker 拒绝(ERR_WORKER_INVALID_EXEC_ARGV)
echo "build exit=$?"构建产物在 .next/(运行期生成,无需打包)。
7. 启动(三选一)
路线 A — launcher(裸机「一键重启」支撑,暴露控制端点)
npm run start:launcher
# 应用监听 PORT(默认 3000);控制端点 127.0.0.1:LAUNCHER_PORT(默认 PORT+1 = 3001)
# POST 127.0.0.1:3001/_restart → 受控重启(先释放端口再拉起,避免 EADDRINUSE)
# GET 127.0.0.1:3001/_ping → 探活路线 B — PM2(推荐生产裸机/云服务器)
# ecosystem.config.js 的 env_production 从 shell 读取,先 export 必填项:
export ADMIN_JWT_SECRET=... SECRET_MASTER_KEY=... ADMIN_USER=admin ADMIN_PASS=...
pm2 start ecosystem.config.js --env production
# 重启:pm2 restart mai-2-dingxin 日志:pm2 logs mai-2-dingxinPM2 配置已固定
instances: 1/exec_mode: fork。严禁改为 cluster 或多实例:本版读缓存为进程内 Map,多副本不会自动失效同步,多实例会导致数据不一致。
路线 C — Docker
# 1) 改 docker-compose.yml:postgres:16-alpine → postgres:18-alpine(匹配备份版本)
# 2) 准备同目录 .env(参考 .env.example),至少填 ADMIN_JWT_SECRET / SECRET_MASTER_KEY / POSTGRES_PASSWORD
docker compose up -d --build
# 容器 mai-2-dingxin-db(5432) + mai-2-dingxin(3000);data/ 由 ./data 卷挂载
# 若库为空,需在宿主机对 db 容器先执行第 4 步恢复,或首次启动用 scripts/migrate-to-pg.mjs 初始化8. 验证
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/zh # 前台中文首页,应 200
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/api/health # Docker 健康检查端点
# launcher 模式额外:
curl -s 127.0.0.1:3001/_ping # 应返回 ok登录后台 /admin/login,确认数据(首页/产品/新闻等)与上传图片正常显示。
9. 端口与进程说明
应用:3000(生产);开发
npm run dev为 3210 / 3211。控制端:仅 launcher 模式在
127.0.0.1:3001暴露/_ping、/_restart(只绑回环,不对外)。PM2 / Docker 不启用该控制端点,分别用
pm2 restart/docker compose restart管理。
10. 常见坑
PG 版本不匹配:用 16 恢复 18 的 dump 会失败;目标 PG 必须 ≥ 18(Docker 改 image 版本)。
NODE_OPTIONS 未清空:构建报
ERR_WORKER_INVALID_EXEC_ARGV;务必NODE_OPTIONS= npm run build。多实例:cluster / instances>1 导致进程内缓存不一致,坚持单副本。
SECRET_MASTER_KEY 丢失:库内已存 API Key 无法解密,需在后台重新填写。
data/uploads 漏复制:图片 404。
.env.local 含密钥:切勿进版本库或公开分发。
四、安全提示
.env.local含数据库密码与各 API Key,切勿提交到公开仓库或随意分发;迁移后与数据库备份分开保管。信封加密的主密钥须与数据库备份分开保存。
数据库备份(
_db_backup/)含全部业务数据,请与代码分开存储。
