# Docker 化部署 本文档说明如何用 Docker Compose 启动完整系统,以及正式部署前需要替换的配置。第一次安装也可参考 [安装与初始设置](./installation.md)。 ## 服务组成 `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`:报告图片、签名、模板图片、视频和关键帧文件。 ## 一键启动 ```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 ``` ## 初始化开关 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`。 - 把 `CORS_ORIGIN` 改成真实前端 HTTPS 来源。 ## 生产部署前必须修改 `docker-compose.yaml` 当前适合演示和院内试运行,生产前至少修改: - `POSTGRES_PASSWORD`:替换默认数据库密码。 - `DATABASE_URL`:与新数据库密码保持一致。 - `SESSION_SECRET`:替换为高强度随机值。 - `CORS_ORIGIN`:只保留真实前端来源。 - `SESSION_COOKIE_SECURE`: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 临时演示参数。