- 新增 Seg_Server_Docker 自包含部署内容,包含前后端、FastAPI、Celery、PostgreSQL、Redis、MinIO、演示视频和 DICOM 数据。 - 保留 demo 数据以支持恢复演示出厂设置,排除 SAM 2.1 .pt 权重并在 README 中补充下载命令。 - 补充 GPU 部署、backend/worker 镜像复用、frpc/frps + NPM 公网域名反代部署说明。 - 在 .env/.env.example 中用 # XXXX 标注局域网和公网域名部署需要修改的配置项。 - 添加部署分支 .gitignore,忽略本地模型权重、构建产物、缓存和日志。
505 lines
14 KiB
Markdown
505 lines
14 KiB
Markdown
# Seg_Server_Docker 部署说明
|
||
|
||
`Seg_Server_Docker` 是语义分割系统的自包含 Docker 部署包。目标不是“最小可运行”,而是尽量完整、可搬迁、能适应 CPU/GPU 与局域网访问等常见环境的可运行版本。
|
||
|
||
部署时只需要保留并移动这一整个文件夹。默认配置只引用本目录内的 `models/`、`demo/`、前端源码、后端源码和 Docker 配置,不依赖旁边的源码仓库,也不依赖固定宿主机路径。
|
||
|
||
## 目录内容
|
||
|
||
```text
|
||
Seg_Server_Docker/
|
||
├── docker-compose.yml # 基础服务:前端、后端、worker、PostgreSQL、Redis、MinIO
|
||
├── docker-compose.gpu.yml # GPU 覆盖配置:给 backend/worker 透传 NVIDIA GPU
|
||
├── Dockerfile.backend # FastAPI + Celery + PyTorch + SAM2 后端镜像
|
||
├── Dockerfile.frontend # React 前端构建 + Nginx 静态服务
|
||
├── .env # 当前部署环境变量
|
||
├── .env.example # 环境变量模板
|
||
├── backend/ # FastAPI 后端代码
|
||
├── src/ # React 前端代码
|
||
├── public/ # 前端静态资源
|
||
├── docker/ # Nginx 配置等 Docker 辅助文件
|
||
├── demo/ # 演示数据
|
||
│ ├── 演视LC视频序列.mp4
|
||
│ └── 演视DICOM序列/
|
||
└── models/ # SAM 2.1 权重,容器内挂载为 /app/models
|
||
```
|
||
|
||
## 服务说明
|
||
|
||
| 服务 | 容器名 | 作用 | 默认端口 |
|
||
|---|---|---|---|
|
||
| frontend | `seg-frontend` | Web 前端页面 | `3000 -> 80` |
|
||
| backend | `seg-backend` | FastAPI API、登录、项目、模板、标注、单帧 AI 分割 | `8000 -> 8000` |
|
||
| worker | `seg-worker` | Celery 后台任务、视频拆帧、DICOM 解析、AI 自动推理/传播 | 内部访问 |
|
||
| postgres | `seg-postgres` | 元数据数据库 | 内部访问 |
|
||
| redis | `seg-redis` | Celery broker/result backend | 内部访问 |
|
||
| minio | `seg-minio` | 视频、DICOM、帧图、缩略图等对象存储 | `9000`、`9001` |
|
||
|
||
`backend` 构建并发布 `seg-server-backend:latest` 镜像,`worker` 直接复用这个镜像。更新后端依赖、PyTorch、SAM2 或系统包时,只需要重建 `backend` 镜像,再同时重启 `backend` 与 `worker`,避免 API 端显示模型可用但 worker 执行传播时缺依赖。
|
||
|
||
`worker` 配置了 `pull_policy: never`,只使用本地 `seg-server-backend:latest`,不会尝试从远端镜像仓库拉取这个内部镜像。首次部署请使用带 `--build` 的启动命令,让 `backend` 先构建出本地镜像。
|
||
|
||
## 部署前准备
|
||
|
||
1. 安装 Docker Engine 和 Docker Compose plugin。
|
||
2. 确认当前目录包含演示数据:
|
||
|
||
```bash
|
||
ls demo/演视LC视频序列.mp4
|
||
ls demo/演视DICOM序列
|
||
```
|
||
|
||
3. 确认当前目录包含 SAM 2.1 权重:
|
||
|
||
```bash
|
||
ls -lh models/
|
||
```
|
||
|
||
推荐至少包含:
|
||
|
||
```text
|
||
models/sam2_hiera_tiny.pt
|
||
models/sam2.1_hiera_small.pt
|
||
models/sam2.1_hiera_base_plus.pt
|
||
models/sam2.1_hiera_large.pt
|
||
```
|
||
|
||
如果只部署部分权重,系统仍可启动;缺失权重对应的模型变体会显示不可用。
|
||
|
||
### 下载 SAM 2.1 权重
|
||
|
||
部署分支不提交 `.pt` 权重文件。首次部署前在本目录执行:
|
||
|
||
```bash
|
||
mkdir -p models
|
||
wget -O models/sam2_hiera_tiny.pt https://dl.fbaipublicfiles.com/segment_anything_2/072824/sam2_hiera_tiny.pt
|
||
wget -O models/sam2.1_hiera_small.pt https://dl.fbaipublicfiles.com/segment_anything_2/092824/sam2.1_hiera_small.pt
|
||
wget -O models/sam2.1_hiera_base_plus.pt https://dl.fbaipublicfiles.com/segment_anything_2/092824/sam2.1_hiera_base_plus.pt
|
||
wget -O models/sam2.1_hiera_large.pt https://dl.fbaipublicfiles.com/segment_anything_2/092824/sam2.1_hiera_large.pt
|
||
```
|
||
|
||
也可以只下载 tiny/small 等需要的权重。`sam2_hiera_tiny.pt` 是兼容旧名,系统会把它作为 `sam2.1_hiera_tiny` 的 fallback 使用。
|
||
|
||
## 环境变量
|
||
|
||
部署前编辑 `.env`:
|
||
|
||
```ini
|
||
PUBLIC_HOST=localhost
|
||
|
||
VITE_API_BASE_URL=
|
||
VITE_WS_PROGRESS_URL=
|
||
|
||
FRONTEND_PORT=3000
|
||
BACKEND_PORT=8000
|
||
MINIO_PORT=9000
|
||
MINIO_CONSOLE_PORT=9001
|
||
|
||
POSTGRES_USER=seguser
|
||
POSTGRES_PASSWORD=segpass123
|
||
POSTGRES_DB=segserver
|
||
|
||
MINIO_ACCESS_KEY=minioadmin
|
||
MINIO_SECRET_KEY=minioadmin
|
||
MINIO_PUBLIC_ENDPOINT=localhost:9000
|
||
MINIO_SECURE=false
|
||
|
||
SAM_MODELS_DIR=./models
|
||
|
||
CORS_ORIGINS=["http://localhost:3000","http://127.0.0.1:3000"]
|
||
|
||
JWT_SECRET_KEY=change-this-to-a-long-random-production-secret
|
||
ACCESS_TOKEN_EXPIRE_MINUTES=1440
|
||
DEFAULT_ADMIN_USERNAME=admin
|
||
DEFAULT_ADMIN_PASSWORD=123456
|
||
```
|
||
|
||
局域网访问时,把 `PUBLIC_HOST` 改成部署机器 IP,并把对应前端地址加入 `CORS_ORIGINS`。例如前端通过 `http://192.168.3.11:3000` 打开时:
|
||
|
||
```ini
|
||
PUBLIC_HOST=192.168.3.11
|
||
VITE_API_BASE_URL=
|
||
VITE_WS_PROGRESS_URL=
|
||
MINIO_PUBLIC_ENDPOINT=192.168.3.11:9000
|
||
MINIO_SECURE=false
|
||
CORS_ORIGINS=["http://192.168.3.11:3000","http://localhost:3000","http://127.0.0.1:3000"]
|
||
```
|
||
|
||
保持 `SAM_MODELS_DIR=./models` 可以让部署包自包含、可搬迁。只有在刻意共享外部模型缓存时,才把它改成其他路径。
|
||
|
||
`.env` 和 `.env.example` 中用 `# XXXX` 标出的配置项,是局域网部署或公网域名反代部署时最常需要修改的地方。
|
||
|
||
生产或长期演示环境请修改:
|
||
|
||
- `JWT_SECRET_KEY`
|
||
- `DEFAULT_ADMIN_PASSWORD`
|
||
- `POSTGRES_PASSWORD`
|
||
- `MINIO_ACCESS_KEY`
|
||
- `MINIO_SECRET_KEY`
|
||
|
||
## CPU 启动
|
||
|
||
适用于没有 NVIDIA GPU 或暂时不配置 GPU 透传的环境:
|
||
|
||
```bash
|
||
docker compose up -d --build
|
||
```
|
||
|
||
查看状态:
|
||
|
||
```bash
|
||
docker compose ps
|
||
curl http://localhost:8000/health
|
||
```
|
||
|
||
CPU 模式下,如果 PyTorch、SAM2 和 `.pt` 权重存在,模型可以加载,但推理速度明显慢于 GPU。
|
||
|
||
## GPU 启动
|
||
|
||
GPU 模式要求宿主机满足:
|
||
|
||
1. NVIDIA 驱动可用。
|
||
2. `nvidia-smi` 能看到 GPU。
|
||
3. Docker 已安装并配置 NVIDIA Container Toolkit。
|
||
4. `docker run --rm --gpus all ... nvidia-smi` 能在容器内看到 GPU。
|
||
|
||
先验证宿主机 GPU:
|
||
|
||
```bash
|
||
nvidia-smi
|
||
```
|
||
|
||
验证 Docker GPU 透传:
|
||
|
||
```bash
|
||
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
|
||
```
|
||
|
||
如果 Docker GPU 验证失败,需要先安装并配置 NVIDIA Container Toolkit:
|
||
|
||
```bash
|
||
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
|
||
| sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
|
||
|
||
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
|
||
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
|
||
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
|
||
|
||
sudo apt-get update
|
||
sudo apt-get install -y nvidia-container-toolkit
|
||
sudo nvidia-ctk runtime configure --runtime=docker
|
||
sudo systemctl restart docker
|
||
```
|
||
|
||
启动 GPU 版:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d --build
|
||
```
|
||
|
||
验证 backend 和 worker 都能看到 GPU:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml exec -T backend python - <<'PY'
|
||
import torch
|
||
print(torch.cuda.is_available())
|
||
print(torch.cuda.device_count())
|
||
print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else "NO CUDA")
|
||
PY
|
||
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml exec -T worker python - <<'PY'
|
||
import torch
|
||
print(torch.cuda.is_available())
|
||
print(torch.cuda.device_count())
|
||
print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else "NO CUDA")
|
||
PY
|
||
```
|
||
|
||
如果 backend 是 GPU 但 worker 不是 GPU,AI 自动推理/传播会失败。此时重建并重启二者:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml build backend
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d backend worker
|
||
```
|
||
|
||
## 公网域名 + frpc/frps + NPM
|
||
|
||
如果公网服务器绑定了域名,并通过 frpc/frps 把内网部署机器端口映射到公网服务器本机端口,再由 Nginx Proxy Manager 反向代理,推荐使用三个子域名:
|
||
|
||
```text
|
||
seg.example.com -> 前端
|
||
seg-api.example.com -> 后端 API + WebSocket
|
||
seg-minio.example.com -> MinIO 图片/帧图/缩略图
|
||
```
|
||
|
||
推荐链路:
|
||
|
||
```text
|
||
浏览器
|
||
-> 公网服务器 NPM
|
||
-> 公网服务器本机 frps 映射端口
|
||
-> frpc
|
||
-> 内网部署机器的 3000 / 8000 / 9000
|
||
```
|
||
|
||
端口映射建议:
|
||
|
||
```text
|
||
内网部署机器 3000 -> 公网服务器本机 13000 -> NPM: seg.example.com
|
||
内网部署机器 8000 -> 公网服务器本机 18000 -> NPM: seg-api.example.com
|
||
内网部署机器 9000 -> 公网服务器本机 19000 -> NPM: seg-minio.example.com
|
||
```
|
||
|
||
NPM 中配置三个 Proxy Host:
|
||
|
||
```text
|
||
seg.example.com
|
||
Scheme: http
|
||
Forward Hostname / IP: 127.0.0.1
|
||
Forward Port: 13000
|
||
|
||
seg-api.example.com
|
||
Scheme: http
|
||
Forward Hostname / IP: 127.0.0.1
|
||
Forward Port: 18000
|
||
Websocket Support: 开启
|
||
|
||
seg-minio.example.com
|
||
Scheme: http
|
||
Forward Hostname / IP: 127.0.0.1
|
||
Forward Port: 19000
|
||
```
|
||
|
||
建议三个域名都在 NPM 里申请 HTTPS 证书,并开启 HTTPS。公网 HTTPS 场景下,内网 `Seg_Server_Docker/.env` 需要修改 `# XXXX` 标出的几项:
|
||
|
||
```ini
|
||
# XXXX Public-domain access through frpc/frps + NPM
|
||
PUBLIC_HOST=seg.example.com
|
||
|
||
# XXXX Frontend build-time API/WebSocket endpoints
|
||
VITE_API_BASE_URL=https://seg-api.example.com
|
||
VITE_WS_PROGRESS_URL=wss://seg-api.example.com/ws/progress
|
||
|
||
# XXXX Browser-facing MinIO endpoint
|
||
MINIO_PUBLIC_ENDPOINT=seg-minio.example.com
|
||
MINIO_SECURE=true
|
||
|
||
# XXXX Browser origins
|
||
CORS_ORIGINS=["https://seg.example.com"]
|
||
```
|
||
|
||
修改 `VITE_API_BASE_URL` 或 `VITE_WS_PROGRESS_URL` 后必须重建前端,因为它们是前端构建期变量:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml build frontend
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d frontend backend worker
|
||
```
|
||
|
||
如果同时从零启动 GPU 版:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d --build
|
||
```
|
||
|
||
公网域名部署后,浏览器只需要访问:
|
||
|
||
```text
|
||
https://seg.example.com
|
||
```
|
||
|
||
不要只反代前端 `3000`。后端 `8000` 不通会导致登录、项目、任务和 AI 接口失败;MinIO `9000` 不通会导致帧图、缩略图、预览图等资源加载失败。
|
||
|
||
## 访问入口
|
||
|
||
默认地址:
|
||
|
||
```text
|
||
前端:http://localhost:3000
|
||
后端:http://localhost:8000
|
||
MinIO API:http://localhost:9000
|
||
MinIO 控制台:http://localhost:9001
|
||
```
|
||
|
||
局域网访问时,把 `localhost` 换成 `.env` 中的 `PUBLIC_HOST`。
|
||
|
||
默认账号:
|
||
|
||
```text
|
||
用户名:admin
|
||
密码:123456
|
||
```
|
||
|
||
## 演示数据和恢复出厂设置
|
||
|
||
演示数据固定从部署包本地读取:
|
||
|
||
```text
|
||
demo/演视LC视频序列.mp4
|
||
demo/演视DICOM序列/
|
||
```
|
||
|
||
系统启动和“恢复演示出厂设置”都会使用这两个路径。恢复后应出现:
|
||
|
||
- `演视LC视频序列`
|
||
- `演视DICOM序列`
|
||
|
||
DICOM 序列会按文件名自然顺序读取,避免切片顺序错位。
|
||
|
||
## 常用运维命令
|
||
|
||
启动:
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
GPU 启动:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d
|
||
```
|
||
|
||
停止:
|
||
|
||
```bash
|
||
docker compose down
|
||
```
|
||
|
||
查看容器:
|
||
|
||
```bash
|
||
docker compose ps
|
||
```
|
||
|
||
查看日志:
|
||
|
||
```bash
|
||
docker compose logs -f backend
|
||
docker compose logs -f worker
|
||
docker compose logs -f frontend
|
||
```
|
||
|
||
重建前后端:
|
||
|
||
```bash
|
||
docker compose build backend frontend
|
||
docker compose up -d backend worker frontend
|
||
```
|
||
|
||
重建 GPU 版后端和 worker:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml build backend
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d backend worker
|
||
```
|
||
|
||
清空当前部署数据:
|
||
|
||
```bash
|
||
docker compose down -v
|
||
docker compose up -d --build
|
||
```
|
||
|
||
注意:`down -v` 会删除数据库和 MinIO 对象存储卷,项目、帧、标注和上传文件都会清空。
|
||
|
||
## 模型状态验证
|
||
|
||
登录后前端左下角会显示 CPU/GPU 状态。也可以通过后端接口检查:
|
||
|
||
```bash
|
||
curl http://localhost:8000/health
|
||
```
|
||
|
||
模型状态接口需要登录 token。更简单的容器内检查方式:
|
||
|
||
```bash
|
||
docker compose exec -T backend python - <<'PY'
|
||
from services.sam_registry import sam_registry
|
||
print(sam_registry.runtime_status())
|
||
PY
|
||
```
|
||
|
||
GPU 版:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml exec -T backend python - <<'PY'
|
||
from services.sam_registry import sam_registry
|
||
print(sam_registry.runtime_status())
|
||
PY
|
||
```
|
||
|
||
## 常见问题
|
||
|
||
### 前端能打开,但图片或缩略图打不开
|
||
|
||
检查 `.env`:
|
||
|
||
- `PUBLIC_HOST` 是否是浏览器可以访问到的主机名或 IP。
|
||
- `MINIO_PORT` 是否开放。
|
||
- `CORS_ORIGINS` 是否包含当前前端地址。
|
||
|
||
修改 `.env` 后重启:
|
||
|
||
```bash
|
||
docker compose up -d backend worker frontend
|
||
```
|
||
|
||
### 左下角显示 CPU
|
||
|
||
先确认是 CPU 部署还是 GPU 部署。GPU 部署必须使用:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d
|
||
```
|
||
|
||
再检查 Docker GPU 透传:
|
||
|
||
```bash
|
||
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
|
||
```
|
||
|
||
如果这条命令失败,问题在宿主机 Docker GPU runtime,不在应用代码。
|
||
|
||
### 单帧 AI 分割可用,但 AI 自动推理无结果
|
||
|
||
检查 `seg-worker` 是否和 `seg-backend` 使用同一个镜像,并且 worker 是否能看到 PyTorch、SAM2 和 GPU:
|
||
|
||
```bash
|
||
docker inspect seg-backend seg-worker --format '{{.Name}} {{.Image}} {{.Config.Image}}'
|
||
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml exec -T worker python - <<'PY'
|
||
import importlib.util, torch
|
||
print("torch", bool(importlib.util.find_spec("torch")))
|
||
print("sam2", bool(importlib.util.find_spec("sam2")))
|
||
print("cuda", torch.cuda.is_available())
|
||
PY
|
||
```
|
||
|
||
如果 worker 缺依赖,重建并重启:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml build backend
|
||
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d backend worker
|
||
```
|
||
|
||
### 恢复演示出厂设置后项目为空
|
||
|
||
检查 demo 文件是否仍在部署包本地:
|
||
|
||
```bash
|
||
ls demo/演视LC视频序列.mp4
|
||
ls demo/演视DICOM序列
|
||
```
|
||
|
||
如果目录被移动或删掉,恢复出厂设置无法重新生成演示项目。
|
||
|
||
### 模型不可用
|
||
|
||
检查 `models/`:
|
||
|
||
```bash
|
||
ls -lh models/
|
||
```
|
||
|
||
缺失的 `.pt` 权重对应模型会显示不可用。部署包默认从 `./models` 挂载到容器内 `/app/models`。
|