本文说明如何在 Windows 本机运行 AutoLabel C++ 的真实 GPU 推理链路。第一版只生成目标类别、置信度和目标框,不包含 SAM。
Windows 浏览器
→ frontend-grounded(127.0.0.1:5174)
→ backend-grounded(127.0.0.1:8081)
→ inference-grounded(Docker 内部 inference-grounded:8001)
→ RAM + GroundingDINO
→ NVIDIA GPU
前端只访问 C++ 网关。C++ 容器通过 Docker 服务名 inference-grounded 访问 Python,不使用容器内的 127.0.0.1。
| Compose | 服务 | 宿主机端口 | 作用 |
|---|---|---|---|
docker-compose.yml |
frontend / backend / inference |
5173 / 8080 / 8000 | Mock 接口与无 GPU 回归 |
docker-compose.grounded.yml |
frontend-grounded / backend-grounded / inference-grounded |
5174 / 8081 / 8001 | RAM + GroundingDINO 真实推理 |
Grounded 的三个端口都显式绑定到宿主机 127.0.0.1。容器内的 Python 服务监听 0.0.0.0:8001,但只有上述 loopback 端口映射对宿主机开放。
- Windows、WSL2 和 Docker Desktop。
- 支持 WSL2 GPU 的 NVIDIA 驱动。
- Docker Desktop 使用 Linux 容器,并且必须保持运行。
- Docker 容器能够访问 NVIDIA GPU。
- 已准备 RAM、GroundingDINO 权重和离线 BERT 缓存。
- 首次构建时能够访问 Docker Hub、Ubuntu、PyPI、PyTorch 和两个官方 GitHub 仓库。
运行容器不需要单独安装 Windows CUDA Toolkit;CUDA 11.8 运行与构建环境包含在官方 NVIDIA 容器镜像中。可以先检查 Docker GPU:
docker run --rm --gpus all nvidia/cuda:11.8.0-cudnn8-devel-ubuntu22.04 nvidia-smi资源和运行数据必须放在仓库外。先从安全模板创建只在本机使用的 .env:
Copy-Item .env.example .env编辑 .env,让两个变量指向已经存在的宿主机目录。目录结构如下:
<AUTOLABEL_ASSETS_DIR>/
├── weights/
│ ├── ram_swin_large_14m.pth
│ └── groundingdino_swint_ogc.pth
└── cache/huggingface/
<AUTOLABEL_DOCKER_DATA_DIR>/
├── logs/
├── uploads/
└── autolabel.sqlite3 # 首次启动网关时创建
权重、BERT 缓存和运行输出不要复制到 Git 仓库。Compose 将权重和 BERT 缓存以只读方式挂载到推理容器。模型服务使用进程内确定性纯灰色 RGB 图像完成 warmup,不依赖外部样本图片。
首次启动前至少要创建两个根目录以及 weights、cache/huggingface 和 logs 子目录;Compose 的 bind mount 源必须真实存在。uploads 和 SQLite 可由网关在可写运行目录中创建。
正常 Grounded 配置默认启用认证。若需要首次初始化管理员,在本机 .env 中同时设置
AUTOLABEL_ADMIN_USERNAME 和长度至少 12 的 AUTOLABEL_ADMIN_PASSWORD;留空则不会创建管理员,仍可在开放注册时创建普通用户。本地 HTTP 保持
AUTOLABEL_COOKIE_SECURE=false,HTTPS 反向代理部署必须改为 true,并把 AUTOLABEL_ALLOWED_ORIGIN 设置为准确的前端 Origin。不要提交包含真实凭据的 .env。
也可以只在当前 PowerShell 会话中覆盖这两个变量:
$env:AUTOLABEL_ASSETS_DIR = "D:/path/to/autolabel-assets"
$env:AUTOLABEL_DOCKER_DATA_DIR = "D:/path/to/autolabel-runtime"实际挂载关系:
| 宿主机目录 | 容器目录 | 权限 |
|---|---|---|
${AUTOLABEL_ASSETS_DIR}/weights |
/models/weights |
只读 |
${AUTOLABEL_ASSETS_DIR}/cache/huggingface |
/models/huggingface |
只读 |
${AUTOLABEL_DOCKER_DATA_DIR}/logs |
/app/logs |
可写 |
${AUTOLABEL_DOCKER_DATA_DIR} |
/app/data |
可写,仅挂给 C++ 网关 |
权重文件名必须是 ram_swin_large_14m.pth 和 groundingdino_swint_ogc.pth。这些 bind mount 内容不通过 Docker build context 写入镜像。
Grounded Compose 的关键运行配置:
| 配置 | Compose 值 | 作用 |
|---|---|---|
INFERENCE_URL |
http://inference-grounded:8001/infer |
C++ 通过服务名调用 Python |
JOB_QUEUE_CAPACITY |
16 | 进程内任务队列容量 |
JOB_WORKER_COUNT |
1 | C++ GPU worker;程序也会强制有效值为 1 |
INFERENCE_CONNECT_TIMEOUT_MS |
5000 | Python 连接超时 |
INFERENCE_TOTAL_TIMEOUT_MS |
120000 | 单次推理总超时 |
TRANSFORMERS_OFFLINE / HF_HUB_OFFLINE |
1 | 运行时禁止在线下载 BERT |
CUDA_VISIBLE_DEVICES |
0 | 容器内选择已分配 GPU |
认证、会话、CORS、指标和文件生命周期变量直接来自 .env.example,由 Compose 以默认值或本机 .env 覆盖传给 C++ 网关。
在项目根目录执行:
docker compose -f docker-compose.grounded.yml config
docker compose -f docker-compose.grounded.yml build
docker compose -f docker-compose.grounded.yml up -d推理镜像会使用以下固定环境:
- Python 3.10
- CUDA 11.8
- PyTorch 2.7.1+cu118
- Torchvision 0.22.1+cu118
- Transformers 5.5.0
- Tokenizers 0.22.2
- Pillow 12.3.0
- RAM
7cb804a8609e9f4b1a50b7f31436d2df40bb9481 - GroundingDINO
856dde20aee659246248e20734ef9ba5214f5e44
Grounded Compose 还固定使用一个 GPU、CUDA_VISIBLE_DEVICES=0、Hugging Face 离线模式、RAM FP16、GroundingDINO FP32 和串行推理。第一次构建和第一次模型加载会比较慢。不要因为 8001 在冷启动期间暂时返回 503 就重复启动第二套推理服务。
镜像已经构建后,普通启动不需要再次执行 build:
docker compose -f docker-compose.grounded.yml up -d
docker compose -f docker-compose.grounded.yml ps健康检查:
curl.exe http://127.0.0.1:5174
curl.exe http://127.0.0.1:8081/health
curl.exe http://127.0.0.1:8081/health/ready
curl.exe http://127.0.0.1:8081/metrics
curl.exe http://127.0.0.1:8001/health
curl.exe http://127.0.0.1:8001/ready
curl.exe http://127.0.0.1:8001/metrics8081/health 检查网关、SQLite 和启动恢复,但不依赖 Python;8081/health/ready 才检查完整链路。Python 的 8001/metrics 返回 JSON 运行快照,C++ 的 8081/metrics 返回 Prometheus 文本。只有 8001/ready 和 8081/health/ready 都返回 HTTP 200 后,才上传图片。
浏览器访问:http://127.0.0.1:5174
C++ 网关文档与在线测试:http://127.0.0.1:8081/docs
C++ 网关 OpenAPI 3.0.3 JSON:http://127.0.0.1:8081/openapi.json
Python 推理服务文档与在线测试:http://127.0.0.1:8001/docs
Python 推理服务 OpenAPI 3.0.3 JSON:http://127.0.0.1:8001/openapi.json
8081 文档页用于验证完整 C++ 网关流程,会校验并保存上传、创建任务并转发给 Python。8001 文档页中的 /infer 测试则把图片原始二进制直接发送给 Python 服务,不经过 C++ 网关,因此不会保存上传文件,也不会创建 SQLite 异步任务。
推理服务:
docker compose -f docker-compose.grounded.yml logs --tail=200 inference-grounded
docker compose -f docker-compose.grounded.yml logs -f inference-groundedC++ 网关:
docker compose -f docker-compose.grounded.yml logs --tail=100 backend-grounded前端:
docker compose -f docker-compose.grounded.yml logs --tail=100 frontend-grounded同时查看三个服务:
docker compose -f docker-compose.grounded.yml logs --tail=100停止 Grounded Compose:
docker compose -f docker-compose.grounded.yml downdown 会停止并删除这套 Compose 的容器和网络,但不会删除仓库外的权重、BERT 缓存、日志和上传文件。不要附加 --volumes、--rmi 或 --remove-orphans,也不要执行 docker system prune 或 docker builder prune。
inference-grounded 停止后,进程持有的 RAM、GroundingDINO 和 CUDA 显存会随容器退出释放。可以用 nvidia-smi 复核;不要把网络停止等同于删除持久化数据。
停止后再次启动不需要重新构建:
docker compose -f docker-compose.grounded.yml up -d需要原地重启时可以执行:
docker compose -f docker-compose.grounded.yml restart无论使用哪种重启方式,8001 都需要重新加载模型。等待 /ready 返回 HTTP 200 后再上传图片。
只更新前端:
docker compose -f docker-compose.grounded.yml build frontend-grounded
docker compose -f docker-compose.grounded.yml up -d --no-deps frontend-grounded只更新 C++ 网关:
docker compose -f docker-compose.grounded.yml build backend-grounded
docker compose -f docker-compose.grounded.yml up -d --no-deps backend-grounded只更新真实推理服务:
docker compose -f docker-compose.grounded.yml build inference-grounded
docker compose -f docker-compose.grounded.yml up -d --no-deps inference-grounded重建推理服务后必须等待 8001 /ready。只重建前端不会重新加载 RAM 或 GroundingDINO。
-
启动 Docker Desktop。
-
等待 Docker Engine 显示 ready。
-
在项目根目录执行:
docker compose -f docker-compose.grounded.yml up -d
-
查看状态和推理日志:
docker compose -f docker-compose.grounded.yml ps docker compose -f docker-compose.grounded.yml logs --tail=200 inference-grounded
-
等待
curl.exe http://127.0.0.1:8001/ready返回 HTTP 200。
- 执行
docker compose -f docker-compose.grounded.yml ps。 - 查看
frontend-grounded日志。 - 检查 Windows 上 5174 是否被其他程序占用。
- 确认前端容器为 healthy,并检查 8081 健康状态。
- 查看
backend-grounded日志。 - 确认
inference-grounded已经 healthy。 - Compose 中网关应使用
http://inference-grounded:8001/infer,不要改成容器内127.0.0.1。 - 检查 Windows 上 8081 是否被其他程序占用。
- 首次模型加载需要等待,先查看推理日志。
- 检查权重文件和离线 BERT 缓存是否存在。
- 检查日志中是否出现
MODEL_MANAGER_READY或MODEL_MANAGER_FAILED。 - 不要同时启动另一份原生模型服务占用 GPU。
执行 GPU 冒烟命令和 nvidia-smi。确认 Docker Desktop 使用 WSL2 Linux 容器、NVIDIA 驱动支持 WSL2 GPU。不要在容器内安装 Linux NVIDIA 驱动,也不要为了排错修改项目模型代码。
确认以下文件存在:
<AUTOLABEL_ASSETS_DIR>/weights/ram_swin_large_14m.pth
<AUTOLABEL_ASSETS_DIR>/weights/groundingdino_swint_ogc.pth
执行 docker compose -f docker-compose.grounded.yml config 检查 .env 中变量展开后的挂载源路径。
真实推理使用完全离线模式。确认 <AUTOLABEL_ASSETS_DIR>/cache/huggingface 包含 bert-base-uncased 的完整缓存。不要把缓存复制到仓库或镜像。
- 先分别测试 Windows 和 Docker 是否能访问
auth.docker.io与registry-1.docker.io。 - 如果 Windows 使用代理,确认代理程序正在运行,并让 Docker Desktop 使用正确的系统代理设置。
- 重启 Docker Desktop 后重试官方镜像。
- 不要关闭 TLS 校验,不要使用来源不明的镜像站,也不要把代理地址或凭据写入 Dockerfile、Compose 或 Git。
5174、8081 和 8001 必须可用。先找出占用端口的明确进程;不要使用模糊 pkill、killall 或 kill -9。如果原生备用服务正在使用这些端口,先通过其经过验证的管理方式停止,再启动 Docker Compose。
- 执行
nvidia-smi和docker stats --no-stream。 - 确认没有第二份 RAM/DINO 服务同时占用 GPU。
- 查看推理日志中的
cuda_out_of_memory。 - 保持单进程、单模型实例和串行请求,不要通过增加 worker 绕过显存限制。
本仓库没有用于管理外部原生 WSL 服务的启动或停止脚本。启动 Docker 链路前应确认原生进程没有占用 5174、8081、8001;不要用模糊进程名强制结束,也不要为本项目执行 wsl --shutdown。
Mock 默认链路:
5173 → 8080 → 8000
启动方式:
docker compose up -dGrounded 真实链路:
5174 → 8081 → 8001 → RAM + GroundingDINO → GPU
启动方式:
docker compose -f docker-compose.grounded.yml up -dMock 结果只能验证接口链路,不能当作真实检测结果。Grounded 结果同样需要人工复核。
Grounded Compose 会把宿主机运行目录整体挂载到 C++ 容器的 /app/data。因此上传图片继续位于 docker-grounded-runtime/uploads,SQLite 任务库位于 docker-grounded-runtime/autolabel.sqlite3。数据库、WAL 和 SHM 文件都不进入 Git 或镜像。
同步网页接口保持不变;异步任务队列、任务查询、Request ID、超时和错误码请参阅 C++ 网关任务队列与持久化。只修改网关时可继续只构建和替换 backend-grounded,不需要重新加载 GPU 模型;修改 Python Request ID 日志后,必须先构建推理镜像,再单独替换并等待 /ready。