- Add docker-compose-Nas.yaml for QNAP/威联通 deployment with NAS persistent data paths, API aliasing, and health checks tailored for NAS firmware. - Parameterize NAS ports, data root, database credentials, proxy variables, CORS, session security, TRUST_PROXY, migrations, and seed settings. - Include an optional frpc profile in the NAS compose file so port 4002 can be exposed through the existing frpc/frpc.toml workflow. - Document NAS startup, health checks, public HTTPS settings, proxy settings, and frpc commands in README. - Update Docker deployment documentation with the NAS compose workflow and the reminder to expose only 4002 publicly.
252 lines
8.2 KiB
Markdown
252 lines
8.2 KiB
Markdown
# Docker 化部署
|
||
|
||
本文档说明如何用 Docker Compose 启动完整系统,以及正式部署前需要替换的配置。第一次安装也可参考 [安装与初始设置](./installation.md)。
|
||
|
||
## 服务组成
|
||
|
||
`docker-compose.yaml` 默认启动三个核心服务,另提供一个可选 frpc 服务:
|
||
|
||
| 服务 | 容器名 | 说明 | 宿主机端口 |
|
||
| --- | --- | --- | --- |
|
||
| `web` | `tuwen_web` | Nginx 托管前端静态文件,并代理 `/api` 到后端 | `4002`、`4443` |
|
||
| `api` | `tuwen_api` | NestJS API、Session、AI/语音代理、文件上传 | `3002` |
|
||
| `db` | `tuwen_db` | PostgreSQL 16 | `5433` |
|
||
| `frpc` | `tuwen_frpc` | `# XXX` 可选公网隧道客户端,通过 `--profile frpc` 启用 | 使用 `frpc/frpc.toml` |
|
||
|
||
持久化 volume:
|
||
|
||
- `postgres_data`:PostgreSQL 数据。
|
||
- `uploads_data`:报告图片、签名、模板图片、视频和关键帧文件。
|
||
|
||
## 一键启动
|
||
|
||
```bash
|
||
docker compose up -d --build
|
||
```
|
||
|
||
首次启动时,`api` 容器会自动执行:
|
||
|
||
1. 等待 PostgreSQL 健康。
|
||
2. `prisma migrate deploy`,把 `server/prisma/migrations` 应用到数据库。
|
||
3. `prisma db seed`,写入默认医院、部门、账号、模板和系统设置。
|
||
4. 启动 NestJS API。
|
||
|
||
访问地址:
|
||
|
||
```text
|
||
前端 HTTP: http://localhost:4002
|
||
前端 HTTPS: https://localhost:4443
|
||
API 健康: http://localhost:3002/api/health
|
||
```
|
||
|
||
查看状态:
|
||
|
||
```bash
|
||
docker compose ps
|
||
```
|
||
|
||
查看日志:
|
||
|
||
```bash
|
||
docker compose logs -f api
|
||
docker compose logs -f web
|
||
docker compose logs -f db
|
||
```
|
||
|
||
停止服务:
|
||
|
||
```bash
|
||
docker compose down
|
||
```
|
||
|
||
连数据库和上传文件一起清空:
|
||
|
||
```bash
|
||
docker compose down -v
|
||
```
|
||
|
||
## 威联通 NAS 部署
|
||
|
||
<!-- # XXX NAS 部署新增:适用于 QNAP/威联通 Container Station 或 NAS 终端 docker compose 部署。 -->
|
||
|
||
NAS 部署可使用仓库内的 `docker-compose-Nas.yaml`:
|
||
|
||
```bash
|
||
docker compose -f docker-compose-Nas.yaml up -d --build
|
||
curl http://127.0.0.1:4002/api/health
|
||
```
|
||
|
||
该配置默认把 PostgreSQL 和上传文件保存到 `/share/Container/tuwen_system_v2/data`,可通过 `NAS_DATA_ROOT` 覆盖。API 诊断端口默认为 `4102`,前端入口仍为 `4002`。
|
||
|
||
公网 HTTPS 部署时建议设置:
|
||
|
||
```bash
|
||
# XXX 生产环境应替换 Session 密钥,并信任 Nginx Proxy Manager/frpc 链路传来的 HTTPS 协议头。
|
||
SESSION_SECRET=替换为足够长的随机字符串
|
||
SESSION_COOKIE_SECURE=true
|
||
TRUST_PROXY=true
|
||
CORS_ORIGIN=http://192.168.31.5:4002,https://sstwbg.example.com
|
||
```
|
||
|
||
启用 NAS 上的 frpc 隧道:
|
||
|
||
```bash
|
||
# XXX 先编辑 frpc/frpc.toml,替换 serverAddr 和 auth.token。
|
||
docker compose -f docker-compose-Nas.yaml --profile frpc up -d --build
|
||
docker compose -f docker-compose-Nas.yaml logs -f frpc
|
||
```
|
||
|
||
`# XXX` 公网正式入口只映射 `4002` 即可;不要把 `4443` 自签名 HTTPS 演示端口映射为公网域名入口。公网 HTTPS 应由 Nginx Proxy Manager 提供。
|
||
|
||
## 初始化开关
|
||
|
||
API 容器启动脚本为 `scripts/docker-api-entrypoint.sh`,可用环境变量控制初始化:
|
||
|
||
| 变量 | 默认值 | 说明 |
|
||
| --- | --- | --- |
|
||
| `RUN_DB_MIGRATIONS` | `true` | 启动 API 前执行 `prisma migrate deploy`。 |
|
||
| `RUN_DB_SEED` | `true` | 启动 API 前执行 `prisma db seed`。当前 seed 使用 upsert,不会清空业务数据。 |
|
||
| `DOCKER_STARTUP_RETRIES` | `30` | migration/seed 等待重试次数。 |
|
||
| `DOCKER_STARTUP_RETRY_DELAY` | `2` | 每次重试间隔秒数。 |
|
||
|
||
如果正式环境希望由运维流水线单独执行 migration,可在 compose 或环境文件中设置:
|
||
|
||
```yaml
|
||
RUN_DB_MIGRATIONS: "false"
|
||
RUN_DB_SEED: "false"
|
||
```
|
||
|
||
然后手动执行:
|
||
|
||
```bash
|
||
docker compose exec api npm run prisma:deploy
|
||
docker compose exec api npm run prisma:seed
|
||
```
|
||
|
||
## 端口和代理
|
||
|
||
- 容器内 API 监听 `3100`,宿主机暴露 `3002`。
|
||
- Nginx 对外暴露 `4002` 和 `4443`。
|
||
- Nginx 将 `/api/` 反向代理到 `api:3100/api/`。
|
||
- `/api/speech/iat` 使用同一条 `/api` 代理路径,并通过 WebSocket upgrade 转发。
|
||
- `client_max_body_size 100m` 与后端 `API_BODY_LIMIT=100mb` 对齐,用于图文报告、图片、视频关键帧和 Data URL 上传。
|
||
|
||
## HTTPS 和麦克风
|
||
|
||
Chrome 不允许普通局域网 HTTP 页面调用麦克风。当前 `Dockerfile` 会生成一个只适合本机演示的自签名证书:
|
||
|
||
```text
|
||
https://localhost:4443
|
||
```
|
||
|
||
如果要用局域网 IP 或域名访问语音听写,应替换 Nginx 证书,并让证书包含实际域名/IP。正式环境建议:
|
||
|
||
- 使用医院内网域名。
|
||
- 通过可信 CA 或内网 CA 签发证书。
|
||
- 把 `SESSION_COOKIE_SECURE` 设为 `true`。
|
||
- 把 `TRUST_PROXY` 设为 `true`。`# XXX` 如果 HTTPS 在 Nginx Proxy Manager、frpc/frps 等外层代理终止,后端需要信任 `X-Forwarded-Proto` 才能正确写入安全 Cookie。
|
||
- 把 `CORS_ORIGIN` 改成真实前端 HTTPS 来源。
|
||
|
||
## 公网域名反向代理
|
||
|
||
<!-- # XXX 公网部署新增:适用于本机 Docker 4002 端口经 frpc 映射到公网服务器,再由 Nginx Proxy Manager 绑定 sstwbg.example.com。 -->
|
||
|
||
如果使用 `本机 Docker 4002 -> frpc -> 公网服务器 Nginx Proxy Manager -> sstwbg.example.com`,推荐流程:
|
||
|
||
```bash
|
||
# XXX 使用公网 HTTPS 入口时,compose 变量可从 shell 或 .env 覆盖。
|
||
export SESSION_SECRET="替换为足够长的随机字符串"
|
||
export SESSION_COOKIE_SECURE="true"
|
||
export TRUST_PROXY="true"
|
||
|
||
# XXX 先编辑 frpc/frpc.toml,替换 serverAddr 和 auth.token,再启用 frpc profile。
|
||
docker-compose --profile frpc up -d --build
|
||
docker-compose logs -f frpc
|
||
```
|
||
|
||
Nginx Proxy Manager 配置要点:
|
||
|
||
- `Domain Names` 使用 `sstwbg.example.com`。
|
||
- `Forward Hostname / IP` 指向 frpc 在公网服务器暴露的地址。
|
||
- `Forward Port` 填 frpc 暴露的端口,例如 `4002`。
|
||
- 开启 `Websockets Support`,保证 `/api/speech/iat` 语音听写 WebSocket 可升级。
|
||
- SSL 页签绑定证书并开启 `Force SSL`,保证浏览器开放麦克风权限。
|
||
- Advanced 中建议设置 `client_max_body_size 100m;`、`proxy_read_timeout 3600s;`、`proxy_send_timeout 3600s;`。
|
||
|
||
`# XXX` 公网正式访问只映射 `4002` 即可;不要把本机自签名 HTTPS 演示入口 `4443` 直接映射为公网域名入口。公网 HTTPS 应由 Nginx Proxy Manager 负责。
|
||
|
||
公网验收先访问 `https://sstwbg.example.com/api/health`,再登录并测试报告保存、视频抽帧、AI 对话和语音听写。
|
||
|
||
## 生产部署前必须修改
|
||
|
||
`docker-compose.yaml` 当前适合演示和院内试运行,生产前至少修改:
|
||
|
||
- `POSTGRES_PASSWORD`:替换默认数据库密码。
|
||
- `DATABASE_URL`:与新数据库密码保持一致。
|
||
- `SESSION_SECRET`:替换为高强度随机值。
|
||
- `CORS_ORIGIN`:只保留真实前端来源。
|
||
- `SESSION_COOKIE_SECURE`:HTTPS 部署时设为 `true`。
|
||
- `TRUST_PROXY`:经反向代理提供 HTTPS 时设为 `true`。
|
||
- `RUN_DB_SEED`:不需要每次启动 seed 时可设为 `false`。
|
||
- AI/讯飞演示凭据:通过系统设置替换为正式凭据;已经暴露过的密钥应轮换。
|
||
- HTTPS 证书:替换自签名本机证书。
|
||
|
||
## 备份与恢复
|
||
|
||
数据库备份:
|
||
|
||
```bash
|
||
docker compose exec db pg_dump -U surclaw surclaw > surclaw_backup.sql
|
||
```
|
||
|
||
上传文件备份:
|
||
|
||
```bash
|
||
docker run --rm -v surclaw_system_uploads_data:/data -v "$PWD":/backup alpine \
|
||
tar czf /backup/uploads_backup.tgz -C /data .
|
||
```
|
||
|
||
恢复数据库前通常需要停服务或进入维护窗口:
|
||
|
||
```bash
|
||
docker compose exec -T db psql -U surclaw -d surclaw < surclaw_backup.sql
|
||
```
|
||
|
||
## 常见问题
|
||
|
||
### API 容器一直 unhealthy
|
||
|
||
查看日志:
|
||
|
||
```bash
|
||
docker compose logs -f api
|
||
```
|
||
|
||
常见原因:
|
||
|
||
- `DATABASE_URL` 密码和 `POSTGRES_PASSWORD` 不一致。
|
||
- 数据库还没健康,等待一段时间或重启 compose。
|
||
- migration 失败,需要检查 `server/prisma/migrations`。
|
||
|
||
### 页面能打开但保存失败
|
||
|
||
检查:
|
||
|
||
```bash
|
||
curl http://localhost:4002/api/health
|
||
curl http://localhost:3002/api/health
|
||
docker compose logs -f api
|
||
```
|
||
|
||
如果报告图片或关键帧很大,确认 `API_BODY_LIMIT` 和 Nginx `client_max_body_size` 都没有被调小。
|
||
|
||
### 语音听写提示麦克风不可用
|
||
|
||
本机演示使用:
|
||
|
||
```text
|
||
https://localhost:4443
|
||
```
|
||
|
||
局域网 HTTP 访问无法由前端代码绕过浏览器限制,只能配置 HTTPS 或使用 Chrome/Edge 临时演示参数。
|