- Add README instructions for deploying the full report system through local Docker port 4002, frpc, Nginx Proxy Manager, and sstwbg.example.com. - Document required HTTPS, WebSocket, request-size, timeout, health-check, login, AI, video-frame, and speech verification steps. - Add TRUST_PROXY support so secure session cookies work behind public HTTPS reverse proxies. - Preserve upstream X-Forwarded-Proto through the container Nginx API proxy. - Allow Docker Compose session and trust-proxy variables to be overridden for public deployments. - Update deployment and Docker docs with the same public reverse-proxy guidance.
6.5 KiB
Docker 化部署
本文档说明如何用 Docker Compose 启动完整系统,以及正式部署前需要替换的配置。第一次安装也可参考 安装与初始设置。
服务组成
docker-compose.yaml 启动三个服务:
| 服务 | 容器名 | 说明 | 宿主机端口 |
|---|---|---|---|
web |
tuwen_web |
Nginx 托管前端静态文件,并代理 /api 到后端 |
4002、4443 |
api |
tuwen_api |
NestJS API、Session、AI/语音代理、文件上传 | 3002 |
db |
tuwen_db |
PostgreSQL 16 | 5433 |
持久化 volume:
postgres_data:PostgreSQL 数据。uploads_data:报告图片、签名、模板图片、视频和关键帧文件。
一键启动
docker compose up -d --build
首次启动时,api 容器会自动执行:
- 等待 PostgreSQL 健康。
prisma migrate deploy,把server/prisma/migrations应用到数据库。prisma db seed,写入默认医院、部门、账号、模板和系统设置。- 启动 NestJS API。
访问地址:
前端 HTTP: http://localhost:4002
前端 HTTPS: https://localhost:4443
API 健康: http://localhost:3002/api/health
查看状态:
docker compose ps
查看日志:
docker compose logs -f api
docker compose logs -f web
docker compose logs -f db
停止服务:
docker compose down
连数据库和上传文件一起清空:
docker compose down -v
初始化开关
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 或环境文件中设置:
RUN_DB_MIGRATIONS: "false"
RUN_DB_SEED: "false"
然后手动执行:
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 会生成一个只适合本机演示的自签名证书:
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 来源。
公网域名反向代理
如果使用 本机 Docker 4002 -> frpc -> 公网服务器 Nginx Proxy Manager -> sstwbg.example.com,推荐流程:
# XXX 使用公网 HTTPS 入口时,compose 变量可从 shell 或 .env 覆盖。
export SESSION_SECRET="替换为足够长的随机字符串"
export SESSION_COOKIE_SECURE="true"
export TRUST_PROXY="true"
docker-compose up -d --build
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;。
公网验收先访问 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 证书:替换自签名本机证书。
备份与恢复
数据库备份:
docker compose exec db pg_dump -U surclaw surclaw > surclaw_backup.sql
上传文件备份:
docker run --rm -v surclaw_system_uploads_data:/data -v "$PWD":/backup alpine \
tar czf /backup/uploads_backup.tgz -C /data .
恢复数据库前通常需要停服务或进入维护窗口:
docker compose exec -T db psql -U surclaw -d surclaw < surclaw_backup.sql
常见问题
API 容器一直 unhealthy
查看日志:
docker compose logs -f api
常见原因:
DATABASE_URL密码和POSTGRES_PASSWORD不一致。- 数据库还没健康,等待一段时间或重启 compose。
- migration 失败,需要检查
server/prisma/migrations。
页面能打开但保存失败
检查:
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 都没有被调小。
语音听写提示麦克风不可用
本机演示使用:
https://localhost:4443
局域网 HTTP 访问无法由前端代码绕过浏览器限制,只能配置 HTTPS 或使用 Chrome/Edge 临时演示参数。