flnxi-Wu/docs/deployment/部署说明.md
2026-06-01 11:40:34 +08:00

485 lines
23 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.

# FLNXI 素材库部署说明
本文档是当前主应用部署入口,合并了原来的快速部署、部署前检查清单和完整部署说明。
先说结论:
- 客户或私有化交付默认按 `NAS(网络存储)` / `Linux(服务器系统)` 现场参数部署。
- 固定服务器、固定端口、固定 Registry 地址只属于内部维护示例,不是客户默认交付口径。
- 客户交付必须显式固定完整 `APP_IMAGE`,例如 `registry.example.com/flnxi/material/flnxi-material:1.0.1`;不要把 `latest` 当成客户部署依据。
- `deploy-registry.ps1` 不再默认指向任何测试服务器,发布和远程部署必须显式传入 `-RegistryHost`,远程部署还必须显式传入 `-Server`。
- 不同品牌 NAS 或客户自有 Linux 服务器交付前,先看 `docs/deployment/多品牌 NAS 与 Linux 交付差异清单.md`。
## 1. 当前部署形态
主应用生产编排文件:
```bash
docker-compose.prod.yml
```
当前会拉起:
- `postgres`:PostgreSQL 数据库
- `minio`:MinIO 对象存储
- `minio-init`:初始化对象存储桶
- `app`:FLNXI 素材库主应用
当前主应用镜像以 Registry 发布链路为准,实际部署时可通过 `.env` 中的 `APP_IMAGE`、`POSTGRES_IMAGE`、`MINIO_IMAGE`、`MINIO_MC_IMAGE` 覆盖。容器名、卷名、网络名和端口也支持用 `.env` 覆盖,下面命令中的 `flnxi-material` 和 `4320` 都只是默认值。
`APP_IMAGE` 是生产启动必填项。这样做是为了让客户现场明确运行哪个版本,避免安装或升级时误拉旧仓库、旧测试镜像或 `latest`。
根目录 `docker-compose.yml` 是本地/历史维护入口,不是客户正式安装入口。客户交付、NAS 和 Linux 私有化部署统一以 `docker-compose.prod.yml + .env` 为准。
当前不会由该 Compose 文件直接拉起:
- Nginx / Traefik 等反向代理
- 独立 `license-server`
- Node 版或 Go 版安装 Agent
这些组件根据交付场景单独部署或由安装 Agent 编排。
独立许可证服务的默认编排在 `license-server/docker-compose.yml`。该编排会由 Nginx 对外暴露 `9527`,再反代到内部 `license-server:3000`;应用容器不再直接暴露宿主机端口。这样登录和 API 限流配置会进入默认链路,避免验证服务器在低配置机器上被暴力请求直接打到 Next 服务。
## 2. 部署前准备
### 2.1 机器条件
建议最低条件:
- CPU:4 核及以上
- 内存:8GB 及以上
- 磁盘:100GB 可用空间
- 系统:Ubuntu 22.04 LTS、群晖 DSM、飞牛 fnOS 或其他支持 Docker 的 Linux 环境
- Docker:Docker 24+ 和 Docker Compose V2
当前主线安装命令按 Docker Compose 验证。Podman / 图形化容器套件属于目标兼容方向,但不同 NAS 的网络、卷权限和健康检查差异很大,客户交付前必须单独实机验证,不能直接把本文的 Docker 命令等同为 Podman 已完整支持。
### 2.2 必填环境变量
部署前至少准备:
```env
POSTGRES_PASSWORD=<generate-a-strong-random-password>
MINIO_ROOT_USER=<generate-a-storage-admin-user>
MINIO_ROOT_PASSWORD=<generate-a-strong-random-password>
APP_IMAGE=registry.example.com/flnxi/material/flnxi-material:1.0.1
SERVER_IP=192.168.x.x
APP_PUBLIC_URL=http://192.168.x.x:4320
NEXTAUTH_URL=http://192.168.x.x:4320
NEXTAUTH_SECRET=<generate-a-strong-random-secret>
S3_BUCKET=flnxi-materials
LICENSE_SERVER_URL=https://your-license-server.example.com
LICENSE_PROJECT_CODE=flnxi-sucai
LICENSE_REQUEST_SIGNING_SECRET=<generate-a-shared-license-request-secret>
LICENSE_PUBLIC_KEY=<license-server-rsa-public-key>
LOCAL_ENCRYPTION_KEY=<generate-a-32-char-or-longer-local-key>
MAX_UPLOAD_FILE_SIZE_BYTES=10737418240
MAX_UPLOAD_TOTAL_FILE_SIZE_BYTES=10737418240
MAX_UPLOAD_FIELD_SIZE_BYTES=2097152
```
说明:
- `SERVER_IP` 必须是用户浏览器能访问到的 NAS / 服务器地址。
- `APP_PUBLIC_URL` 必须和最终访问入口一致,用于生成公开访问、分享和回调相关地址。
- `NEXTAUTH_URL` 必须和最终访问入口一致。
- `APP_IMAGE` 必须写完整镜像地址和版本号,不要只写 `latest`。
- `POSTGRES_IMAGE`、`MINIO_IMAGE`、`MINIO_MC_IMAGE` 建议同样固定版本;离线或受控网络交付时,应写成私有 Registry 里的固定版本镜像。
- `LICENSE_PROJECT_CODE` 必须和 `license-server` 中项目表的 `projects.code` 一致。
- `LICENSE_REQUEST_SIGNING_SECRET` 必须和 `license-server` 的同名变量一致,至少 32 字符,用于主应用到验证服务器的请求签名。
- `LICENSE_PUBLIC_KEY` 是许可证服务签发许可证时使用的 RSA 公钥,主应用靠它确认许可证没有被伪造。
- `LOCAL_ENCRYPTION_KEY` 用于主应用本地加密保存许可证缓存,至少 32 字符,不能使用示例值。
- `MAX_UPLOAD_FILE_SIZE_BYTES` 是单个素材文件上限;`MAX_UPLOAD_TOTAL_FILE_SIZE_BYTES` 是一次上传请求总上限;`MAX_UPLOAD_FIELD_SIZE_BYTES` 是表单文字字段总上限。示例值分别是 10GB、10GB、2MB,低配 NAS 可按客户机器内存和磁盘调小。
- 不要把真实密码、许可证地址、对象存储密钥写入 Git。
数据库有两种模式:
- 内置 PostgreSQL:`DATABASE_URL` 留空或不写,由 `docker-compose.prod.yml` 按 `POSTGRES_USER`、`POSTGRES_PASSWORD`、`POSTGRES_DB` 自动拼接到 `postgres` 服务。
- 外部 PostgreSQL:才填写真实 `DATABASE_URL`,例如 `postgresql://flnxi:<password>@192.168.1.10:5432/flnxi?sslmode=disable`。
对象存储也有两种模式:
- 内置 MinIO:`S3_ENDPOINT=http://minio:9000`,`S3_ACCESS_KEY_ID` / `S3_SECRET_ACCESS_KEY` 可不填,Compose 会使用 `MINIO_ROOT_USER` / `MINIO_ROOT_PASSWORD`。`S3_PUBLIC_DOMAIN` 必须写成用户浏览器能访问的地址,例如 `http://192.168.1.20:9000/flnxi-materials`。
- 外部 S3 / 外部 MinIO:需要填写真实 `S3_ENDPOINT`、`S3_ACCESS_KEY_ID`、`S3_SECRET_ACCESS_KEY`、`S3_BUCKET`、`S3_PUBLIC_DOMAIN`,并确认 bucket 已存在或当前账号有创建和读写权限。
NAS 或 Linux 服务器上建议提前准备挂载目录:
```bash
mkdir -p uploads data
chown -R 1001:1001 uploads data
chmod 775 uploads data
```
如果客户系统启用了更严格的用户权限,需让运行主应用容器的用户可以写入这两个目录;当前镜像内应用用户通常按 UID `1001` 理解。飞牛 / NAS 场景里,第一次手工创建目录如果是 root 所有权,单纯 `chmod 775` 可能还是不够,优先把目录属主改成 `1001:1001`。最简单的验收标准是:容器启动后能上传素材,`uploads/` 和 `data/` 没有持续出现权限拒绝日志。
### 2.3 HTTP Registry 前置检查
如果 Registry 使用 `http://`,本机 Docker 和目标机器 Docker 都要先允许这个 Registry。否则会出现 `HTTP response to HTTPS client`,表现为登录、推送或拉取镜像失败。
Linux 目标机常见配置:
```json
{
"insecure-registries": ["registry.example.com:5000"]
}
```
配置位置通常是 `/etc/docker/daemon.json`。改完后重启 Docker:
```bash
sudo systemctl restart docker
docker info | grep -A 5 "Insecure Registries"
```
Docker Desktop 需要在设置里的 Docker Engine 配置同样的 `insecure-registries`,保存并重启 Docker。
## 3. 标准部署步骤
### 3.1 区分首装和升级
当前交付链路分三段看,不能混成一个命令:
- 发布方构建和推送镜像:使用 `deploy-registry.ps1` 的发布动作,产出固定版本镜像。
- 客户首次安装:在目标机器准备部署目录、`docker-compose.prod.yml`、`.env`、数据卷和固定版本镜像,然后启动 Compose。
- 已有客户升级:使用 `deploy-registry.ps1 -Action DeployApp` 写入新 `APP_IMAGE`,并执行备份、拉取、迁移、健康检查和失败回滚。
`deploy-registry.ps1 -Action DeployApp` 默认假设远端已经有部署目录、生产 Compose 和 `.env`,它是升级/远程更新入口,不是单独完整的首装向导。
### 3.2 准备环境文件
在目标机器部署目录准备 `.env`:
```bash
cp .env.example .env
```
再按实际环境补齐数据库、MinIO、NextAuth、许可证和访问地址。首装使用内置 PostgreSQL 时,不要给 `DATABASE_URL` 填占位连接串;外部 PostgreSQL 才填写真实连接串。
### 3.3 启动服务
正式客户交付先通过 `deploy-registry.ps1` 完成版本化镜像发布,并把远端 `.env` 里的 `APP_IMAGE` 写到目标版本,再执行下面的启动命令。
```bash
docker compose -f docker-compose.prod.yml up -d
```
生产 Compose 只读取 `APP_IMAGE`,不包含 `build:`。如果需要重新构建镜像,应在发布方机器使用 `deploy-registry.ps1` 或内部构建脚本先生成版本镜像,再更新 `.env`。
离线或受控网络交付时,启动前还要确认 `APP_IMAGE`、`POSTGRES_IMAGE`、`MINIO_IMAGE`、`MINIO_MC_IMAGE` 都已经在目标机器 Docker 或客户私有 Registry 中存在。否则 `docker compose up -d` 会因为无法拉取镜像而失败。
### 3.4 初始化数据库
主应用容器入口脚本 `scripts/docker-entrypoint.sh` 会在启动时自动执行:
```bash
npx prisma migrate deploy
```
所以常规部署不需要手动再跑一次数据库迁移。
如果历史模板数据需要补齐,或自动迁移失败后要人工补救,再按实际容器名执行:
```bash
docker exec <APP_CONTAINER_NAME> npm run migrate:template-data
docker exec <APP_CONTAINER_NAME> npm run verify:template-data
```
默认容器名是 `flnxi-material`;如果 `.env` 配了 `APP_CONTAINER_NAME`,以实际值为准。
如是全新环境,继续按 `docs/初次部署与出厂设置指南.md` 走系统初始化流程。
### 3.5 验证服务
```bash
docker compose -f docker-compose.prod.yml ps
curl http://<SERVER_IP>:4320/api/health
docker logs flnxi-material --tail 100
```
`/api/health` 返回 `200` 表示应用启动检查已通过;如果返回 `503`,先查看 `docker logs flnxi-material --tail 100`,通常是数据库连接、迁移或内置模板初始化未完成。
如果 `.env` 覆盖了 `APP_PORT` 或 `APP_CONTAINER_NAME`,验证命令也要同步替换成实际端口和容器名。
页面验证:
- 登录页:`http://<SERVER_IP>:4320/login`
- 首页:`http://<SERVER_IP>:4320`
- 管理后台:`http://<SERVER_IP>:4320/admin`
- 模板管理:在 `http://<SERVER_IP>:4320/admin` 后台内打开;当前没有独立的 `/admin/templates` 路由
## 4. 版本化 Registry 发布
当前仓库的主发布脚本是 `deploy-registry.ps1`,用于构建、推送和远程更新主应用、Agent 以及运行时镜像。它默认会把版本镜像写入远端 `.env`,客户升级不要再回退到默认 `latest`。
`DeployApp` 远程部署现在默认包含第一轮升级保护:
- 升级前在远端创建 `backups/deploy-时间戳/`,保存升级前 `.env`。
- 如果远端 PostgreSQL 是当前 Compose 管理的 `postgres` 服务,会先执行 `pg_dump` 备份;如果使用外部数据库,会提示需要确认外部备份。
- 如果远端 MinIO 是当前 Compose 管理的 `minio` 服务,会先把 `MINIO_VOLUME_NAME` 对应的数据卷打包备份;如果使用外部 S3 / 外部 MinIO,会在备份目录写入提示文件,要求按客户现场方案单独备份对象存储。
- 备份目录会生成 `RESTORE_PLAN.txt`,把本次 `.env`、PostgreSQL、MinIO 备份文件和 L1/L2/L3 恢复命令列出来,便于升级失败时按影响范围恢复。
- 部署失败时默认尝试恢复升级前 `.env`,并按旧运行镜像或旧 `APP_IMAGE` 重建应用容器。
- 部署后会在远端校验应用容器实际运行镜像、镜像内 `VERSION.txt` 和 Prisma 迁移状态,然后再做外部 `/api/health` 检查。
只有在已有其它备份和回滚体系时,才考虑使用 `-NoRemoteDbBackup`、`-NoRemoteObjectStorageBackup` 或 `-NoRollback`。离线客户现场如果没有 `busybox:1.36`,需要先把该 helper 镜像放到目标机,或通过 `-RemoteBackupHelperImage` 指定现场已有的小型 Linux 镜像。
必须注意:脚本的自动回滚只恢复应用镜像和 `.env`,不自动恢复数据库和对象存储。只要本次升级包含数据库迁移或素材文件结构变化,升级前的数据库备份和对象存储备份就必须保留,并按 `RESTORE_PLAN.txt` 的 L2/L3 步骤由人工确认后恢复。
典型用法:
```powershell
$registryPassword = Read-Host 'Registry密码' -AsSecureString
$sshPassword = Read-Host 'SSH密码' -AsSecureString
.\deploy-registry.ps1 -Action DeployApp -DeployChannel release -Version 1.0.1 -RegistryHost registry.example.com:5000 -Server 192.168.1.20 -RegistryPassword $registryPassword -Password $sshPassword
.\deploy-registry.ps1 -Action PublishRelease -Version 1.0.1 -RegistryHost registry.example.com:5000 -RegistryPassword $registryPassword
.\deploy-registry.ps1 -Action PublishAgent -Version 1.0.1 -RegistryHost registry.example.com:5000 -RegistryPassword $registryPassword
.\deploy-registry.ps1 -Action SyncRuntime -RegistryHost registry.example.com:5000 -RegistryPassword $registryPassword
```
说明:
- 客户升级和内部发布优先按版本 tag 走,不要把 `latest` 当成客户部署依据。
- 客户现场部署使用 `-DeployChannel release -Version x.x.x`;测试通道只用于内部验证,必须显式传 `-DeployChannel test`。
- `DeployApp` 远程部署时默认会更新远端 `.env` 的 `APP_IMAGE`、访问地址和运行时镜像;只有临时验证时才使用 `-NoUpdateRemoteEnv`。
- `DeployApp` 默认会做远端 `.env` 备份、Compose PostgreSQL 备份、Compose MinIO 备份、恢复分级说明、失败自动回滚、运行镜像校验、版本文件校验和 Prisma 迁移状态校验。
- 旧的 `deploy-new-fixed.ps1` 仍可作为内部维护参考,但不再作为当前主线部署入口。
- 如果要做远程更新,先确认 `Registry`、SSH、`.env` 和目标机器都属于当前维护环境。
### 4.1 镜像体积基线
发布前可以对主应用镜像做一次体积和分层记录:
```powershell
.\scripts\measure-image-size.ps1 `
-Image "registry.example.com/flnxi/material/flnxi-material:1.0.1" `
-OutputPath ".\reports\image-size-1.0.1.md"
```
这个脚本不会改镜像,只会读取 Docker 本地镜像信息,列出总大小、层数和最大的若干层。后续做镜像瘦身时,先用这个报告确认是 `ffmpeg`、字体、`canvas`、`node_modules` 还是 Prisma 迁移工具占用更大,再决定是否拆成可选能力或独立迁移镜像。
## 5. 部署前检查清单
- [ ] 已确认目标机器品牌、系统和 Docker Compose 支持情况;如使用 Podman,已单独实机验证
- [ ] 已确认端口、域名、证书、反向代理方案
- [ ] 已确认数据目录、对象存储目录和备份位置
- [ ] 已确认升级失败时使用 L1 应用回滚、L2 数据库恢复还是 L3 数据库+素材恢复
- [ ] `.env` 已填写真实环境变量;内置 PostgreSQL 模式下 `DATABASE_URL` 没有错误占位值
- [ ] `APP_IMAGE` 已固定到完整版本镜像,不使用 `latest`
- [ ] 如果 Registry 是 HTTP,本机和目标机 Docker 都已配置 `insecure-registries`
- [ ] `NEXTAUTH_URL` 与最终访问地址一致
- [ ] `S3_BUCKET`、`S3_PUBLIC_DOMAIN` 口径正确
- [ ] `LICENSE_SERVER_URL` 和 `LICENSE_PROJECT_CODE` 已确认
- [ ] `LICENSE_REQUEST_SIGNING_SECRET` 已配置且与许可证服务一致
- [ ] `LICENSE_PUBLIC_KEY`、`LOCAL_ENCRYPTION_KEY` 已配置为真实值
- [ ] `uploads/`、`data/` 目录对应用容器可写
- [ ] 已执行与本次改动相关的测试或命令
- [ ] 涉及数据库变更时已有备份和回滚方案
## 6. 部署后冒烟测试
启动前可以先做一轮不启动容器的安装前检查:
```powershell
.\scripts\smoke-install.ps1 -ProjectDir "D:\deploy\flnxi" -PreflightOnly
```
如果是新目录,还希望脚本顺手创建 `uploads/` 和 `data/`,可以加:
```powershell
.\scripts\smoke-install.ps1 -ProjectDir "D:\deploy\flnxi" -PreflightOnly -PrepareDirectories
```
这一步会提前拦截 `.env` 示例值、`latest` 镜像、缺失数据目录和明显错误的访问地址,避免等容器启动失败后再排查。
首装后优先使用脚本做基础验收:
```powershell
.\scripts\smoke-install.ps1 -ProjectDir "D:\deploy\flnxi" -Start
```
如果服务已经由 NAS 图形界面或其他编排入口启动,可以去掉 `-Start`,只做检查:
```powershell
.\scripts\smoke-install.ps1 -ProjectDir "D:\deploy\flnxi"
```
该脚本会先做安装前检查,再检查 Compose 配置、容器状态、应用运行镜像、镜像内版本文件、Prisma 迁移状态、MinIO bucket 和 `/api/health`。如果客户使用外部对象存储,加 `-SkipObjectStorageCheck`,对象存储验收按客户现场方案单独执行。
人工验收命令仍保留如下:
- [ ] `/api/health` 正常
- [ ] 登录 / 退出正常
- [ ] 首次初始化或激活流程正常
- [ ] 首页素材列表可加载
- [ ] 素材上传、预览、下载正常
- [ ] 后台模板管理可打开
- [ ] 系统设置可读取和保存
- [ ] 许可证状态显示正确
- [ ] 容器日志没有持续错误
## 7. 数据备份与回滚
`deploy-registry.ps1 -Action DeployApp` 会默认做一轮升级前备份和失败回滚。下面命令主要用于人工兜底、外部数据库场景或单独恢复演练。
### 7.1 一键备份
首选脚本:
```powershell
.\scripts\backup-restore.ps1 -ProjectDir "D:\deploy\flnxi" -Action Backup
```
默认备份内容:
- `.env`
- `docker-compose.prod.yml`
- `VERSION.txt`,如果部署目录里存在
- `compose-config.txt`、`compose-ps.txt`、`docker-images.txt`
- Compose 管理的 PostgreSQL:`postgres.sql`
- Compose 管理的 MinIO 数据卷:`minio-data.tar.gz`
- `manifest.json`:记录备份时间、应用镜像、访问地址、服务名等关键信息
`DeployApp` 升级时生成的 `backups/deploy-时间戳/RESTORE_PLAN.txt` 是升级恢复指引;`backup-restore.ps1 -Action Backup` 生成的 `flnxi-backup-时间戳/manifest.json` 是完整备份包记录。两者用途不同,客户升级失败时优先看当次升级目录里的 `RESTORE_PLAN.txt`。
如果 `DATABASE_URL` 指向外部 PostgreSQL,脚本不会假装自动备份,会在备份目录写入 `EXTERNAL_DATABASE_BACKUP_REQUIRED.txt`,客户现场必须按外部数据库方案单独备份。
如果对象存储是外部 S3 / 外部 MinIO,或现场已有独立对象存储快照,可加:
```powershell
.\scripts\backup-restore.ps1 -ProjectDir "D:\deploy\flnxi" -Action Backup -SkipObjectStorageBackup
```
内置 MinIO 备份/恢复默认使用 `busybox:1.36` 作为 helper 镜像。离线客户现场需要提前把该镜像放进 Docker,或通过 `-HelperImage` 指定现场已有的 Linux 工具镜像。
### 7.2 一键验收
```powershell
.\scripts\backup-restore.ps1 -ProjectDir "D:\deploy\flnxi" -Action Verify
```
该动作会检查 Compose 配置、容器状态和 `/api/health`,适合备份前、恢复后、升级后快速确认系统是否可用。
### 7.3 一键恢复
恢复会覆盖客户数据,必须停写入并确认备份来源正确。脚本要求输入固定确认短语,避免误操作:
```powershell
.\scripts\backup-restore.ps1 `
-ProjectDir "D:\deploy\flnxi" `
-Action Restore `
-BackupPath "D:\deploy\flnxi\backups\flnxi-backup-YYYYMMDD-HHMMSS" `
-ConfirmRestore RESTORE_FLNXI_DATA
```
说明:
- 默认恢复 `postgres.sql` 和 `minio-data.tar.gz`,然后启动服务并执行健康验收。
- 如果只恢复数据库、不恢复对象存储,加 `-SkipObjectStorageRestore`。
- 如果需要把备份包中的 `.env` 一起恢复,加 `-RestoreEnv`;脚本会先把当前 `.env` 另存为 `.env.before-restore-时间戳`。
- 外部数据库和外部对象存储不受该脚本自动恢复,必须按客户现场备份方案操作。
### 7.4 手动备份数据库
```bash
docker exec flnxi-postgres pg_dump \
-U postgres \
-d flnxi \
-F c \
-f /tmp/flnxi-backup-$(date +%Y%m%d-%H%M%S).dump
```
再把备份文件复制到宿主机或外部备份位置。外部数据库不受 Compose 脚本管理,必须按客户现场数据库方案单独备份。
### 7.5 手动回滚应用
如使用镜像部署,回滚到上一镜像版本时,直接改完整 `APP_IMAGE`。不要只改 `IMAGE_TAG`,因为完整 `APP_IMAGE` 的优先级更高。
```bash
docker compose -f docker-compose.prod.yml down
cp .env .env.rollback-$(date +%Y%m%d-%H%M%S)
sed -i 's#^APP_IMAGE=.*#APP_IMAGE=registry.example.com/flnxi/material/flnxi-material:<previous-version>#' .env
docker compose -f docker-compose.prod.yml pull app
docker compose -f docker-compose.prod.yml up -d app
curl http://<SERVER_IP>:4320/api/health
```
回滚后 `/api/health` 仍必须返回 `200` 才算应用恢复可用。
回滚前先确认数据库是否需要同时回滚。只回滚应用镜像不等于回滚数据库结构;如果本次升级包含数据库迁移,必须先确认备份和恢复路径。
### 7.6 手动恢复数据库
恢复前必须确认已停止会写入数据库的应用容器,并确认备份文件正确。下面给两种常见方式,二选一即可。
```bash
docker cp ./flnxi-backup-YYYYMMDD-HHMMSS.dump flnxi-postgres:/tmp/flnxi-restore.dump
docker exec flnxi-postgres pg_restore \
-U postgres \
-d flnxi \
-c \
/tmp/flnxi-restore.dump
```
或者直接从宿主机标准输入恢复:
```bash
docker exec -i flnxi-postgres pg_restore \
-U postgres \
-d flnxi \
-c \
< ./flnxi-backup-YYYYMMDD-HHMMSS.dump
```
## 8. 常见问题
### 应用访问不到
优先检查:
- `docker compose -f docker-compose.prod.yml ps`
- `APP_PORT` 是否和访问端口一致
- `SERVER_IP` 和 `NEXTAUTH_URL` 是否填写成浏览器可访问地址
- 防火墙是否放通端口
### MinIO 预览或下载异常
优先检查:
- `S3_BUCKET`
- `MINIO_ROOT_USER`
- `MINIO_ROOT_PASSWORD`
- `S3_PUBLIC_DOMAIN`
- MinIO 控制台是否能看到桶和对象
- `S3_SET_ACL` 是否仍为默认 `0`。私有化交付默认不公开素材桶;只有兼容旧公开对象模式时才允许显式改成 `1`。
- 当前生产 Compose 的 `minio-init` 会默认执行 `mc anonymous set none`,用于关闭 MinIO 桶匿名下载。如果客户历史环境曾经公开过桶,升级后应重跑 `minio-init` 或手动执行同等命令确认桶已恢复私有。
- 外部 S3 或历史环境可能存在旧 bucket policy、旧对象级 ACL 或历史公开链接,这些不一定会被当前 `minio-init` 自动收回,升级前后要单独做只读审计。
### 许可证异常
优先检查:
- `LICENSE_SERVER_URL`
- `LICENSE_PROJECT_CODE`
- `LICENSE_REQUEST_SIGNING_SECRET` 是否与许可证服务一致
- 许可证服务是否存在对应项目编码
- 主应用 `/api/license/check`、`/api/license/verify` 响应
- 如果独立部署 `license-server/docker-compose.yml`,确认对外访问的是 Nginx 暴露的 `9527`,不是容器内部 `3000`。
- 如果请求返回 `429`,优先检查 Nginx 限流是否被触发,再看是否存在脚本重试、暴力激活或心跳频率异常。
### 数据迁移失败
优先查看:
```bash
docker logs flnxi-material --tail 200
docker exec flnxi-material npx prisma validate
docker exec flnxi-material npm run verify:template-data
```
## 9. 相关文档
- `docs/初次部署与出厂设置指南.md`
- `docs/deployment/多品牌 NAS 与 Linux 交付差异清单.md`
- `docs/许可证服务接入说明.md`
- `scripts/README.md`