Complete Docker compose deployment setup

- Add an API container entrypoint that waits for PostgreSQL, runs Prisma migrations, seeds demo data, and then starts NestJS.

- Keep Prisma CLI and seed dependencies available in the API runtime image and copy seed source dependencies into the container.

- Add Docker Compose healthchecks and health-based startup ordering for PostgreSQL, API, and Nginx web services.

- Add Docker initialization environment switches for migrations, seed, and startup retries.

- Add a dedicated Docker deployment guide covering services, ports, initialization, HTTPS, production variables, backup, restore, and troubleshooting.

- Update README, AGENTS, installation, deployment, progress, and environment example docs for the Dockerized workflow.
This commit is contained in:
2026-05-02 05:38:03 +08:00
parent 2cabe7e4fd
commit 5d936832da
12 changed files with 269 additions and 8 deletions

185
docs/docker.md Normal file
View File

@@ -0,0 +1,185 @@
# 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 临时演示参数。