阿里云单机 RAG、知识图谱与文档解析项目部署技术方案

阿里云单机 RAG、知识图谱与文档解析项目部署技术方案

状态:已在阿里云 ECS + Tesla T4 上完成部署并通过端到端验证
适用范围:测试、验证、低并发内部使用
不适用范围:需要高可用、横向扩展、零停机、开放公网访问的生产环境

本文档记录一套从购买阿里云 ECS 开始,完整部署以下服务的可复现方案:

  • Milvus Standalone
  • etcd(Milvus 内部元数据依赖)
  • Neo4j Community
  • MongoDB
  • MinIO
  • BGE-M3 dense + sparse 混合向量服务
  • BGE Reranker(TEI)
  • MinerU API
  • MinerU Gradio Web UI
  • MinerU pipelinevlm-auto-enginehybrid-auto-engine 三种解析模式

文档中的公网 IP、密码和 ACR 用户名全部使用占位符。执行前必须替换,不要把真实密码提交到仓库。

本文部署的是 shopkeeper_brain 所依赖的外部基础设施和 GPU 推理服务,不包含 Python
业务进程本身。当前仓库没有统一的 Python 依赖锁定文件,因此业务运行环境需另行维护。

本文是当前单机栈的部署基线。仓库中 2026-05 的 MinerU 设计和 Runbook 记录的是旧服务器、
旧目录及旧 CUDA 组合,只用于历史排障,不应覆盖本文的镜像版本和 Compose 配置。


1. 最终架构

本地开发电脑(安全组白名单 IP)
  |
  | SSH / HTTP / gRPC / Bolt
  v
阿里云 ECS(单机,Docker Compose)
  |
  +-- MinIO :9000/:9001
  |     +-- shopkeeper-files   业务文件 bucket
  |     `-- milvus-data        Milvus 专用 bucket
  |
  +-- MongoDB :27017
  +-- Neo4j :7474/:7687
  +-- etcd :2379               仅 Docker 内网
  +-- Milvus :19530
  |
  +-- BGE-M3 :8894             dense + sparse
  +-- BGE Reranker :8891       /rerank
  +-- MinerU API :8893         PDF -> Markdown
  `-- MinerU Gradio :8895      浏览器上传与解析
        |
        `-- Tesla T4 16 GB(与 BGE/Reranker 共享)

1.1 Docker 网络

所有容器加入同一个用户定义网络:

shopkeeper-network

容器之间使用 Compose 服务名访问:

Milvus -> etcd:2379
Milvus -> minio:9000
Gradio -> mineru:80

etcd 不映射宿主机端口,不对公网开放。

1.2 存储设计

测试环境只使用系统盘,所有持久化数据放在:

/opt/shopkeeper-stack/data

Docker 自身数据位于:

/var/lib/docker

Milvus 复用业务 MinIO 实例,但使用独立账号、独立 bucket 和独立对象前缀:

业务账号:shopkeeper-app
业务 bucket:shopkeeper-files

Milvus 账号:milvus-storage
Milvus bucket:milvus-data
Milvus rootPath:shopkeeper-milvus

Milvus 并非必须使用“MinIO 这个产品”,但 Standalone 仍需要一个受支持的对象存储保存
insert log、index 等持久化对象。可根据版本改接 S3 或兼容对象存储;本方案使用 MinIO,
因为单机部署简单且已验证。etcd 是另一项独立依赖,用于保存 collection schema、segment
状态、协调信息等元数据,不能用 MinIO 代替,也不应对公网开放。


2. 已验证版本矩阵

组件已验证版本/规格
操作系统Ubuntu 22.04.5 LTS
CPU8 vCPU,Intel Xeon Platinum 8163
内存31 GiB 规格,系统可见约 29 GiB
Swap8 GiB
GPUNVIDIA Tesla T4 16 GB
NVIDIA Driver580.126.09
宿主 CUDA 能力CUDA 13.0
Docker Engine29.5.1
Docker Compose5.1.3
Milvus2.5.27
etcd3.5.18
MinIORELEASE.2024-12-18T13-15-44Z
MinIO ClientRELEASE.2024-11-21T17-21-54Z
MongoDB8.0.24 noble
Neo4j5.26 Community
TEIcuda-1.9
BGE-M3BAAI/bge-m3
BGE-M3 Torch2.4.0+cu121
RerankerBAAI/bge-reranker-large
MinerU3.1.9
MinerU Torch2.13.0+cu130
MinerU TorchVision0.28.0+cu130

注意:MinerU 的最终版本组合依赖兼容 CUDA 13 的 NVIDIA 驱动。若目标服务器仍是旧驱动,不能直接照搬该组合。

2.1 本次部署验收结果

验收项结果
MinIO API、Console、两个独立 bucket/账号/策略通过
MongoDB 认证与 ping通过
Neo4j Bolt 认证与 RETURN 1通过
etcd 健康检查通过
Milvus 健康检查、认证、空 collection 列表通过
BGE-M3 dense 1024 维向量通过
BGE-M3 sparse 非零特征通过
BGE Reranker 将 iPhone 15 排在 index 0通过
MinerU API、Swagger、Gradio通过
MinerU pipeline PDF 解析通过
MinerU vlm-auto-engine PDF 解析通过
MinerU hybrid-auto-engine PDF 解析通过
白名单本地 IP 访问全部对外端口通过

3. 服务器选型与购买

3.1 推荐测试规格

配置项推荐值
实例族ecs.gn6i-c8g1.2xlarge 或同等级 T4 实例
CPU/内存8 vCPU / 31 GiB
GPUTesla T4 16 GB x 1
系统Ubuntu 22.04 64 位
系统盘150 GiB ESSD;若在 ECS 上构建镜像,不建议低于 150 GiB
数据盘测试环境可不添加
付费方式按量付费,连续测试不建议抢占式
公网带宽按流量,峰值 5-10 Mbps
驱动NVIDIA Driver 580,CUDA 13

3.2 为什么推荐 150 GiB

本次部署完成后主要磁盘占用来自:

  • PyTorch 基础镜像
  • BGE-M3 服务镜像
  • TEI CUDA 镜像
  • MinerU CUDA 13 镜像
  • Pipeline 与 VLM 模型
  • Docker 构建缓存

本次在 ECS 上完成全部构建、模型下载后,系统盘曾使用约 94 GiB。100 GiB
只有在以下条件同时成立时才勉强适用:自定义镜像已经在其他机器构建并推送到 ACR、ECS
只拉取运行镜像、及时清理构建缓存、测试数据很少。若要按照本文在 ECS 上直接构建
BGE-M3 和 MinerU,使用 150 GiB,避免构建导出或解包阶段因磁盘不足失败。

3.3 镜像和应用环境

购买时选择:

Ubuntu 22.04 64 位
安装 GPU 驱动
Docker 社区版

不需要安装:

  • 宝塔面板
  • Linux 桌面
  • Java
  • Node.js
  • Go
  • 系统级 Python 开发环境

阿里云自动生成的 GPU 驱动安装“自定义数据”脚本应保留。实例启动后可能自动重启一次,等待 10-20 分钟再验证 GPU。


4. 安全组与公网访问

4.1 获取本地公网 IP

在本地电脑执行:

curl -4 https://ifconfig.me

假设返回:

1.2.3.4

安全组来源填写:

1.2.3.4/32

4.2 入方向规则

所有规则的来源均为本地公网 IP /32,禁止使用 0.0.0.0/0

端口服务用途
22SSH服务器管理
19530MilvusPython SDK / REST
7474Neo4jBrowser Web UI
7687Neo4jBolt
27017MongoDB数据库连接
9000MinIOS3 API
9001MinIOConsole
8891BGE Reranker/rerank
8893MinerU API异步任务 API
8894BGE-M3/embed/embed_sparse
8895MinerU GradioWeb UI

以下端口不要开放:

端口原因
2379/2380etcd 仅供 Milvus 内部访问
9091Milvus 管理端口不需要公网访问
7473未配置 Neo4j HTTPS

Docker 的 ports 默认可能同时显示 0.0.0.0[::]。如果 ECS 分配了公网 IPv6,
还必须检查 IPv6 安全组:不添加 ::/0 入方向规则;确需 IPv6 访问时,仅放行本地公网
IPv6 的 /128。只配置 IPv4 /32 不能自动限制公网 IPv6。

4.3 安全边界说明

本方案依赖“安全组 IP 白名单 + 服务自身账号密码”,没有为所有服务配置 TLS。测试环境可以接受,生产环境必须至少选择以下一种方式:

  • VPN / WireGuard / Zero Trust 网络
  • 阿里云专有网络内访问
  • TLS/HTTPS/Bolt TLS/MongoDB TLS/Milvus TLS
  • 反向代理和统一身份认证

MinerU 使用了 --allow-public-http-client,允许请求携带远程推理地址,存在 SSRF 风险。因此 88938895 必须严格限制来源 IP。

BGE-M3、BGE Reranker、MinerU API 和 MinerU Gradio 当前都没有应用层认证;对于这些端口,
阿里云安全组白名单就是主要访问边界。不要仅依赖 UFW,因为 Docker 发布端口时会管理宿主机
防火墙规则。若安全组出方向被收紧,模型下载和镜像拉取还需要允许 DNS、HTTP 和 HTTPS。


5. ECS 初始化

5.1 登录和基础检查

ssh root@<ECS_PUBLIC_IP>
cat /etc/os-release
uname -a
timedatectl
df -h /
free -h
lscpu | grep -E 'CPU\(s\)|Model name'

设置时区:

timedatectl set-timezone Asia/Shanghai

安装工具:

apt update
apt install -y \
  curl wget git jq unzip vim htop tree nload \
  ca-certificates gnupg lsb-release openssl \
  python3-venv

5.2 配置 8 GiB Swap

fallocate -l 8G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
grep -q '^/swapfile ' /etc/fstab || \
  echo '/swapfile none swap sw 0 0' >> /etc/fstab
cat >/etc/sysctl.d/99-shopkeeper.conf <<'EOF'
vm.swappiness=10
vm.max_map_count=262144
EOF

sysctl --system

验证:

free -h
swapon --show
sysctl vm.swappiness vm.max_map_count

5.3 验证 GPU 和 Docker

nvidia-smi
nvidia-container-cli info
docker version
docker compose version
systemctl status docker --no-pager

预期:

  • nvidia-smi 显示 Tesla T4
  • nvidia-container-cli info 能识别设备
  • Docker daemon 为 running
  • Docker Compose 可用

6. 配置阿里云 Docker Hub 加速

中国大陆 ECS 直接访问 Docker Hub 可能超时。进入:

容器镜像服务 ACR -> 镜像工具 -> 镜像加速器

获取账号专属地址:

https://<YOUR_MIRROR_ID>.mirror.aliyuncs.com

先确保配置文件存在,再备份 NVIDIA runtime 配置:

test -f /etc/docker/daemon.json || printf '{}\n' >/etc/docker/daemon.json
cp /etc/docker/daemon.json /etc/docker/daemon.json.bak

必须先安装 jq,不要在 jq 失败后把空临时文件覆盖回正式配置:

apt install -y jq

合并配置:

MIRROR_URL='https://<YOUR_MIRROR_ID>.mirror.aliyuncs.com'

jq --arg url "$MIRROR_URL" \
  '. + {"registry-mirrors": [$url]}' \
  /etc/docker/daemon.json \
  > /etc/docker/daemon.json.tmp \
  && jq empty /etc/docker/daemon.json.tmp \
  && mv /etc/docker/daemon.json.tmp /etc/docker/daemon.json

结果应同时保留 NVIDIA runtime:

{
  "runtimes": {
    "nvidia": {
      "args": [],
      "path": "nvidia-container-runtime"
    }
  },
  "registry-mirrors": [
    "https://<YOUR_MIRROR_ID>.mirror.aliyuncs.com"
  ]
}

重启:

systemctl daemon-reload
systemctl restart docker
systemctl status docker --no-pager

验证:

docker info | sed -n '/Registry Mirrors/,+5p'
docker info | grep -i -A2 runtimes

6.1 验证容器 GPU

阿里云加速器可能没有同步 nvidia/cuda,可以使用 Ubuntu 镜像验证 NVIDIA runtime:

docker pull ubuntu:22.04
docker run --rm --gpus all ubuntu:22.04 nvidia-smi

容器内能够看到 Tesla T4 即通过。


7. ACR 镜像仓库规划与同步

7.1 仓库规划

在杭州地域 ACR 个人版中创建命名空间:

shopkeeper-brain

创建私有仓库:

mongo
neo4j
milvus
pytorch
bge-m3-server
bge-reranker
mineru-server

地址:

公网:registry.cn-hangzhou.aliyuncs.com
VPC:registry-vpc.cn-hangzhou.aliyuncs.com

本地 Mac 使用公网地址;同地域 ECS 使用 VPC 地址。

7.2 本地 Mac 登录 ACR

docker login \
  --username='<ACR_USERNAME>' \
  registry.cn-hangzhou.aliyuncs.com

密码使用 ACR“访问凭证”设置的固定密码,不要把密码写进命令。

7.3 ECS 登录 ACR VPC 地址

docker login \
  --username='<ACR_USERNAME>' \
  registry-vpc.cn-hangzhou.aliyuncs.com

7.4 从 Mac 同步基础镜像

Apple Silicon Mac 必须显式指定 linux/amd64,否则推送到 ACR 的架构无法在 x86 ECS 上运行。

docker pull --platform linux/amd64 mongo:8.0.24-noble
docker pull --platform linux/amd64 neo4j:5.26-community
docker pull --platform linux/amd64 milvusdb/milvus:v2.5.27
docker pull --platform linux/amd64 \
  pytorch/pytorch:2.4.0-cuda12.1-cudnn9-runtime
docker pull --platform linux/amd64 \
  ghcr.io/huggingface/text-embeddings-inference:cuda-1.9

打标签:

ACR_PUBLIC=registry.cn-hangzhou.aliyuncs.com/shopkeeper-brain

docker tag mongo:8.0.24-noble \
  "$ACR_PUBLIC/mongo:8.0.24-noble"

docker tag neo4j:5.26-community \
  "$ACR_PUBLIC/neo4j:5.26-community"

docker tag milvusdb/milvus:v2.5.27 \
  "$ACR_PUBLIC/milvus:v2.5.27"

docker tag pytorch/pytorch:2.4.0-cuda12.1-cudnn9-runtime \
  "$ACR_PUBLIC/pytorch:2.4.0-cuda12.1-cudnn9-runtime"

docker tag ghcr.io/huggingface/text-embeddings-inference:cuda-1.9 \
  "$ACR_PUBLIC/bge-reranker:tei-1.9"

推送:

ACR_PUBLIC=registry.cn-hangzhou.aliyuncs.com/shopkeeper-brain

docker push "$ACR_PUBLIC/mongo:8.0.24-noble"
docker push "$ACR_PUBLIC/neo4j:5.26-community"
docker push "$ACR_PUBLIC/milvus:v2.5.27"
docker push "$ACR_PUBLIC/pytorch:2.4.0-cuda12.1-cudnn9-runtime"
docker push "$ACR_PUBLIC/bge-reranker:tei-1.9"

7.5 ECS 拉取基础镜像

Quay.io 镜像可直接拉取:

docker pull quay.io/coreos/etcd:v3.5.18
docker pull quay.io/minio/minio:RELEASE.2024-12-18T13-15-44Z
docker pull quay.io/minio/mc:RELEASE.2024-11-21T17-21-54Z

ACR 镜像走 VPC:

ACR_VPC=registry-vpc.cn-hangzhou.aliyuncs.com/shopkeeper-brain

docker pull "$ACR_VPC/mongo:8.0.24-noble"
docker pull "$ACR_VPC/neo4j:5.26-community"
docker pull "$ACR_VPC/milvus:v2.5.27"
docker pull "$ACR_VPC/pytorch:2.4.0-cuda12.1-cudnn9-runtime"
docker pull "$ACR_VPC/bge-reranker:tei-1.9"

8. 创建部署目录

mkdir -p /opt/shopkeeper-stack/{config,scripts,backups}
mkdir -p /opt/shopkeeper-stack/data/{etcd,minio,milvus,neo4j,mongodb}
mkdir -p /opt/shopkeeper-stack/data/neo4j/{data,logs}
mkdir -p /opt/shopkeeper-stack/data/mongodb/db
mkdir -p /opt/shopkeeper-stack/data/minio/data
mkdir -p /opt/shopkeeper-stack/data/etcd/data
mkdir -p /opt/shopkeeper-stack/data/mineru/output
mkdir -p /opt/shopkeeper-stack/models/{bge-m3,reranker,mineru}
mkdir -p /opt/shopkeeper-stack/services/{bge-m3,reranker,mineru}
tree -L 3 /opt/shopkeeper-stack
docker info --format 'Docker Root Dir: {{.DockerRootDir}}'
df -h /

9. 生成部署环境变量

进入目录并设置严格文件权限:

cd /opt/shopkeeper-stack
umask 077

生成 .env

cat > .env <<EOF
COMPOSE_FILE=compose.yaml:compose.gpu.yaml
ACR_VPC=registry-vpc.cn-hangzhou.aliyuncs.com/shopkeeper-brain

MINIO_ROOT_USER=minio-root
MINIO_ROOT_PASSWORD=$(openssl rand -hex 24)

MINIO_APP_USER=shopkeeper-app
MINIO_APP_PASSWORD=$(openssl rand -hex 24)
MINIO_APP_BUCKET=shopkeeper-files

MINIO_MILVUS_USER=milvus-storage
MINIO_MILVUS_PASSWORD=$(openssl rand -hex 24)
MINIO_MILVUS_BUCKET=milvus-data

MONGO_ROOT_USERNAME=shopkeeper-admin
MONGO_ROOT_PASSWORD=$(openssl rand -hex 24)

NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=$(openssl rand -hex 24)

MILVUS_ROOT_PASSWORD=$(openssl rand -hex 24)
EOF

chmod 600 .env

只显示变量名,不显示密码:

awk -F= 'NF && $1 !~ /^#/ {print $1"=<已设置>"}' .env

将真实值保存到密码管理器。不要把 .env 上传到 Git 或发送到聊天工具。

.env 只能在首次部署时生成一次。MongoDB、Neo4j、Milvus 等服务会把初始化认证信息
写入持久化目录;服务启动后重新运行上述生成命令,会导致 .env 中的密码与已有数据
中的密码不一致。后续维护只能恢复原 .env,不能直接重新生成。


10. 配置共享 MinIO

10.1 业务 bucket 策略

cd /opt/shopkeeper-stack
set -a
source .env
set +a
cat > config/minio-app-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetBucketLocation", "s3:ListBucket"],
      "Resource": ["arn:aws:s3:::${MINIO_APP_BUCKET}"]
    },
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
      "Resource": ["arn:aws:s3:::${MINIO_APP_BUCKET}/*"]
    }
  ]
}
EOF

10.2 Milvus bucket 策略

cat > config/minio-milvus-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetBucketLocation",
        "s3:ListBucket",
        "s3:ListBucketMultipartUploads"
      ],
      "Resource": ["arn:aws:s3:::${MINIO_MILVUS_BUCKET}"]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:AbortMultipartUpload",
        "s3:ListMultipartUploadParts"
      ],
      "Resource": ["arn:aws:s3:::${MINIO_MILVUS_BUCKET}/*"]
    }
  ]
}
EOF

chmod 600 config/minio-*-policy.json
jq empty config/minio-app-policy.json
jq empty config/minio-milvus-policy.json

10.3 MinIO 初始化脚本

cat > scripts/init-minio.sh <<'EOF'
#!/bin/sh
set -eu

until mc alias set local http://minio:9000 \
  "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD"; do
  sleep 2
done

mc mb --ignore-existing "local/$MINIO_APP_BUCKET"
mc mb --ignore-existing "local/$MINIO_MILVUS_BUCKET"

mc admin user info local "$MINIO_APP_USER" >/dev/null 2>&1 ||
  mc admin user add local "$MINIO_APP_USER" "$MINIO_APP_PASSWORD"

mc admin user info local "$MINIO_MILVUS_USER" >/dev/null 2>&1 ||
  mc admin user add local "$MINIO_MILVUS_USER" "$MINIO_MILVUS_PASSWORD"

mc admin policy info local shopkeeper-app-policy >/dev/null 2>&1 ||
  mc admin policy create local shopkeeper-app-policy \
    /policies/minio-app-policy.json

mc admin policy info local milvus-storage-policy >/dev/null 2>&1 ||
  mc admin policy create local milvus-storage-policy \
    /policies/minio-milvus-policy.json

mc admin policy attach local shopkeeper-app-policy \
  --user "$MINIO_APP_USER"

mc admin policy attach local milvus-storage-policy \
  --user "$MINIO_MILVUS_USER"

echo "MinIO buckets、users 和 policies 初始化完成"
EOF

chmod 700 scripts/init-minio.sh

11. Milvus 增量配置

必须使用 /milvus/configs/user.yaml 做增量覆盖,不能把下面的局部配置挂载成完整 milvus.yaml

即使重新登录过 ECS,也先重新加载部署变量:

cd /opt/shopkeeper-stack
set -a
source .env
set +a
cat > config/user.yaml <<EOF
etcd:
  rootPath: shopkeeper-milvus

minio:
  address: minio
  port: 9000
  accessKeyID: "${MINIO_MILVUS_USER}"
  secretAccessKey: "${MINIO_MILVUS_PASSWORD}"
  useSSL: false
  bucketName: "${MINIO_MILVUS_BUCKET}"
  rootPath: shopkeeper-milvus
  useIAM: false
  cloudProvider: aws
  useVirtualHost: false

common:
  security:
    authorizationEnabled: true
    defaultRootPassword: "${MILVUS_ROOT_PASSWORD}"
    enablePublicPrivilege: false
EOF

chmod 600 config/user.yaml

defaultRootPassword 只对首次初始化的新 Milvus 数据生效。已有数据目录不会因为修改 YAML 自动更换密码。


12. 基础服务 Compose

创建 /opt/shopkeeper-stack/compose.yaml

cat > compose.yaml <<'EOF'
name: shopkeeper-stack

services:
  minio:
    image: quay.io/minio/minio:RELEASE.2024-12-18T13-15-44Z
    container_name: shopkeeper-minio
    command: server /data --console-address ":9001"
    restart: unless-stopped
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - ./data/minio/data:/data
    mem_limit: 2g
    networks: [shopkeeper]

  minio-init:
    image: quay.io/minio/mc:RELEASE.2024-11-21T17-21-54Z
    container_name: shopkeeper-minio-init
    entrypoint: /bin/sh
    command: /scripts/init-minio.sh
    restart: "no"
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
      MINIO_APP_USER: ${MINIO_APP_USER}
      MINIO_APP_PASSWORD: ${MINIO_APP_PASSWORD}
      MINIO_APP_BUCKET: ${MINIO_APP_BUCKET}
      MINIO_MILVUS_USER: ${MINIO_MILVUS_USER}
      MINIO_MILVUS_PASSWORD: ${MINIO_MILVUS_PASSWORD}
      MINIO_MILVUS_BUCKET: ${MINIO_MILVUS_BUCKET}
    volumes:
      - ./scripts/init-minio.sh:/scripts/init-minio.sh:ro
      - ./config:/policies:ro
    depends_on:
      - minio
    networks: [shopkeeper]

  mongodb:
    image: ${ACR_VPC}/mongo:8.0.24-noble
    container_name: shopkeeper-mongodb
    command: ["mongod", "--auth", "--bind_ip_all", "--wiredTigerCacheSizeGB", "1"]
    restart: unless-stopped
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USERNAME}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD}
    ports:
      - "27017:27017"
    volumes:
      - ./data/mongodb/db:/data/db
    mem_limit: 3g
    networks: [shopkeeper]

  neo4j:
    image: ${ACR_VPC}/neo4j:5.26-community
    container_name: shopkeeper-neo4j
    restart: unless-stopped
    environment:
      NEO4J_AUTH: ${NEO4J_USERNAME}/${NEO4J_PASSWORD}
      NEO4J_server_memory_heap_initial__size: 512m
      NEO4J_server_memory_heap_max__size: 1g
      NEO4J_server_memory_pagecache_size: 1g
    ports:
      - "7474:7474"
      - "7687:7687"
    volumes:
      - ./data/neo4j/data:/data
      - ./data/neo4j/logs:/logs
    mem_limit: 3g
    networks: [shopkeeper]

  etcd:
    image: quay.io/coreos/etcd:v3.5.18
    container_name: shopkeeper-etcd
    command:
      - etcd
      - --advertise-client-urls=http://etcd:2379
      - --listen-client-urls=http://0.0.0.0:2379
      - --data-dir=/etcd
      - --auto-compaction-mode=revision
      - --auto-compaction-retention=1000
      - --quota-backend-bytes=4294967296
    restart: unless-stopped
    volumes:
      - ./data/etcd/data:/etcd
    healthcheck:
      test: ["CMD", "etcdctl", "endpoint", "health"]
      interval: 10s
      timeout: 5s
      retries: 10
    mem_limit: 1g
    networks: [shopkeeper]

  milvus:
    image: ${ACR_VPC}/milvus:v2.5.27
    container_name: shopkeeper-milvus
    command: ["milvus", "run", "standalone"]
    restart: unless-stopped
    security_opt:
      - seccomp:unconfined
    environment:
      ETCD_ENDPOINTS: etcd:2379
      MINIO_ADDRESS: minio:9000
    ports:
      - "19530:19530"
    volumes:
      - ./config/user.yaml:/milvus/configs/user.yaml:ro
      - ./data/milvus:/var/lib/milvus
    depends_on:
      etcd:
        condition: service_healthy
      minio-init:
        condition: service_completed_successfully
    mem_limit: 12g
    networks: [shopkeeper]

networks:
  shopkeeper:
    name: shopkeeper-network
    driver: bridge
EOF

chmod 600 compose.yaml

此时 compose.gpu.yaml 还不存在。为使 docker compose config 可先运行,创建空的 GPU Compose:

cat > compose.gpu.yaml <<'EOF'
services: {}
EOF

chmod 600 compose.gpu.yaml

校验:

docker compose config --quiet
docker compose config --services

13. 分阶段启动基础服务

13.1 启动 MinIO

docker compose up -d minio
sleep 5
docker compose ps minio
docker compose logs --tail=50 minio

单机模式出现“host failure will result in data unavailable”警告是预期行为。

初始化 bucket、账号和策略:

docker compose run --rm minio-init

预期:

Bucket created successfully `local/shopkeeper-files`.
Bucket created successfully `local/milvus-data`.
Added user `shopkeeper-app` successfully.
Added user `milvus-storage` successfully.
MinIO buckets、users 和 policies 初始化完成

13.2 启动 MongoDB、Neo4j 和 etcd

docker compose up -d mongodb neo4j etcd
sleep 20
docker compose ps

检查重启次数:

docker inspect \
  --format '{{.Name}} status={{.State.Status}} restart={{.RestartCount}}' \
  shopkeeper-mongodb shopkeeper-neo4j shopkeeper-etcd

预期均为:

status=running restart=0

13.3 启动 Milvus

docker compose up -d milvus
sleep 30
docker compose ps milvus
docker compose logs --tail=120 milvus

健康检查:

docker exec shopkeeper-milvus \
  curl -fsS http://127.0.0.1:9091/healthz

预期:

OK

日志应包含:

remote chunk manager init success
bucketname=milvus-data
root=shopkeeper-milvus
All components are ready

14. 验证基础服务认证

cd /opt/shopkeeper-stack
set -a
source .env
set +a

14.1 MongoDB

docker exec shopkeeper-mongodb mongosh --quiet \
  -u "$MONGO_ROOT_USERNAME" \
  -p "$MONGO_ROOT_PASSWORD" \
  --authenticationDatabase admin \
  --eval 'db.adminCommand({ping: 1})'

预期:

{ ok: 1 }

14.2 Neo4j

docker exec shopkeeper-neo4j cypher-shell \
  -u "$NEO4J_USERNAME" \
  -p "$NEO4J_PASSWORD" \
  'RETURN 1 AS result;'

预期:

result
1

14.3 Milvus

curl -sS http://127.0.0.1:19530/v2/vectordb/collections/list \
  -H "Authorization: Bearer root:${MILVUS_ROOT_PASSWORD}" \
  -H "Content-Type: application/json" \
  -d '{"dbName":"default"}'

空库预期:

{"code":0,"data":[]}

15. 创建模型下载环境

不要用系统 pip 安装 ModelScope。始终使用虚拟环境的绝对路径:

python3 -m venv /opt/shopkeeper-stack/model-downloader
/opt/shopkeeper-stack/model-downloader/bin/python -m pip install -U pip \
  -i https://mirrors.aliyun.com/pypi/simple/

/opt/shopkeeper-stack/model-downloader/bin/python -m pip install modelscope \
  -i https://mirrors.aliyun.com/pypi/simple/

验证:

/opt/shopkeeper-stack/model-downloader/bin/python -m pip --version

输出路径必须包含 /opt/shopkeeper-stack/model-downloader/


16. 下载 BGE-M3 模型

/opt/shopkeeper-stack/model-downloader/bin/python - <<'PY'
from modelscope import snapshot_download

path = snapshot_download(
    "BAAI/bge-m3",
    local_dir="/opt/shopkeeper-stack/models/bge-m3",
)
print("模型目录:", path)
PY

验证:

du -sh /opt/shopkeeper-stack/models/bge-m3
find /opt/shopkeeper-stack/models/bge-m3 \
  -maxdepth 1 -type f -printf '%f\n' | sort

必须包含:

config.json
pytorch_model.bin
sparse_linear.pt
colbert_linear.pt
tokenizer.json
sentencepiece.bpe.model

17. 构建 BGE-M3 dense + sparse 服务

仓库源码位置:

infra/bge-m3-server/

17.1 上传源码

在本地项目根目录执行:

cd /path/to/shopkeeper_brain

scp \
  infra/bge-m3-server/Dockerfile \
  infra/bge-m3-server/requirements.txt \
  infra/bge-m3-server/server.py \
  root@<ECS_PUBLIC_IP>:/opt/shopkeeper-stack/services/bge-m3/

17.2 改用 ACR VPC 基础镜像

在 ECS 执行:

cd /opt/shopkeeper-stack
set -a
source .env
set +a
cd services/bge-m3

sed -i \
  '1c FROM registry-vpc.cn-hangzhou.aliyuncs.com/shopkeeper-brain/pytorch:2.4.0-cuda12.1-cudnn9-runtime' \
  Dockerfile

17.3 构建和推送

set -o pipefail

docker build \
  --progress=plain \
  -t "$ACR_VPC/bge-m3-server:1.0" \
  . 2>&1 | tee build.log
docker push "$ACR_VPC/bge-m3-server:1.0"

18. 下载 Reranker 模型

只下载 TEI 所需文件,避免额外下载 ONNX/OpenVINO 和重复权重:

/opt/shopkeeper-stack/model-downloader/bin/python - <<'PY'
from modelscope import snapshot_download

path = snapshot_download(
    "BAAI/bge-reranker-large",
    local_dir="/opt/shopkeeper-stack/models/reranker",
    allow_patterns=[
        "config.json",
        "model.safetensors",
        "tokenizer.json",
        "tokenizer_config.json",
        "special_tokens_map.json",
        "sentencepiece.bpe.model",
    ],
)
print("模型目录:", path)
PY

验证:

du -sh /opt/shopkeeper-stack/models/reranker
find /opt/shopkeeper-stack/models/reranker \
  -maxdepth 1 -type f -printf '%f\n' | sort

核心文件:

config.json
model.safetensors
tokenizer.json
tokenizer_config.json
sentencepiece.bpe.model

Reranker 使用前面已同步到 ACR 的 TEI 镜像:

${ACR_VPC}/bge-reranker:tei-1.9

19. 构建 MinerU 镜像

仓库源码位置:

infra/mineru/

当前已验证的关键依赖:

mineru[core]==3.1.9
torch 2.13.0+cu130
torchvision 0.28.0+cu130

19.1 上传源码

在本地项目根目录:

scp \
  infra/mineru/Dockerfile \
  infra/mineru/requirements.txt \
  root@<ECS_PUBLIC_IP>:/opt/shopkeeper-stack/services/mineru/

19.2 改用 ACR VPC 基础镜像

cd /opt/shopkeeper-stack
set -a
source .env
set +a
cd services/mineru

sed -i \
  '1c FROM registry-vpc.cn-hangzhou.aliyuncs.com/shopkeeper-brain/pytorch:2.4.0-cuda12.1-cudnn9-runtime' \
  Dockerfile

19.3 构建

set -o pipefail

docker build \
  --progress=plain \
  -t "$ACR_VPC/mineru-server:1.0.1" \
  . 2>&1 | tee build-1.0.1.log

19.4 验证 Torch/TorchVision/CUDA

docker run --rm --gpus all \
  --entrypoint python \
  "$ACR_VPC/mineru-server:1.0.1" \
  -c 'import torch,torchvision; print("torch",torch.__version__); print("torchvision",torchvision.__version__); print("cuda",torch.cuda.is_available(),torch.cuda.get_device_name(0)); print("torchvision extension",torchvision.extension._has_ops())'

必须满足:

torch 2.13.0+cu130
torchvision 0.28.0+cu130
cuda True Tesla T4
torchvision extension True

推送:

docker push "$ACR_VPC/mineru-server:1.0.1"

20. 下载 MinerU Pipeline 和 VLM 模型

重新进入部署目录、加载镜像仓库变量并创建目录:

cd /opt/shopkeeper-stack
set -a
source .env
set +a

mkdir -p /opt/shopkeeper-stack/models/mineru
mkdir -p /opt/shopkeeper-stack/data/mineru/output

20.1 Pipeline 模型

docker run --rm \
  -e HOME=/root \
  -e MINERU_MODEL_SOURCE=modelscope \
  -v /opt/shopkeeper-stack/models/mineru:/root \
  --entrypoint mineru-models-download \
  "$ACR_VPC/mineru-server:1.0.1" \
  -s modelscope \
  -m pipeline

20.2 VLM 模型

备份 pipeline 配置:

cp /opt/shopkeeper-stack/models/mineru/mineru.json \
  /opt/shopkeeper-stack/models/mineru/mineru.json.pipeline.bak

下载 VLM:

docker run --rm \
  -e HOME=/root \
  -e MINERU_MODEL_SOURCE=modelscope \
  -v /opt/shopkeeper-stack/models/mineru:/root \
  --entrypoint mineru-models-download \
  "$ACR_VPC/mineru-server:1.0.1" \
  -s modelscope \
  -m vlm

检查:

du -sh /opt/shopkeeper-stack/models/mineru
cat /opt/shopkeeper-stack/models/mineru/mineru.json
df -h /

同一个 /root/mineru.json 应包含 pipeline 与 VLM 的本地模型配置。

20.3 三种解析引擎的选择

引擎主要路径优点代价与建议
pipeline版面分析、OCR、公式、表格等专用模型流水线显存压力相对低,行为稳定,适合常规产品手册作为 T4 单卡默认模式
vlm-auto-engineVLM 自动解析路径对复杂视觉版式、扫描件和语义关联更有优势更慢、显存峰值更高,单任务运行
hybrid-auto-enginePipeline 与 VLM 的混合/自动选择路径兼顾结构化提取和复杂页面适应性路径最复杂,适合 Pipeline 效果不足时使用

具体路由行为会随 MinerU 版本和文档内容变化。测试环境固定 MinerU 3.1.9,并将默认
模式设为 pipeline;VLM 与 Hybrid 作为按需选项,三种模式都必须在上线前用真实手册抽样验收。


21. GPU 服务 Compose

用完整配置替换之前的空 compose.gpu.yaml

cd /opt/shopkeeper-stack

cat > compose.gpu.yaml <<'EOF'
services:
  bge-m3:
    image: ${ACR_VPC}/bge-m3-server:1.0
    container_name: shopkeeper-bge-m3
    restart: unless-stopped
    gpus: all
    environment:
      BGE_M3_PATH: /data/model
      BGE_FP16: "true"
      BGE_MAX_LEN: "8192"
    ports:
      - "8894:80"
    volumes:
      - ./models/bge-m3:/data/model:ro
    shm_size: 2g
    mem_limit: 4g
    healthcheck:
      test:
        - CMD
        - python
        - -c
        - "import json,urllib.request; assert json.load(urllib.request.urlopen('http://127.0.0.1/health'))['status']=='ok'"
      interval: 15s
      timeout: 10s
      retries: 20
      start_period: 120s
    networks: [shopkeeper]

  bge-reranker:
    image: ${ACR_VPC}/bge-reranker:tei-1.9
    container_name: shopkeeper-bge-reranker
    restart: unless-stopped
    gpus: all
    command:
      - --model-id
      - /data/model
      - --dtype
      - float16
      - --max-client-batch-size
      - "32"
      - --max-batch-tokens
      - "16384"
      - --auto-truncate
    ports:
      - "8891:80"
    volumes:
      - ./models/reranker:/data/model:ro
    shm_size: 1g
    mem_limit: 4g
    networks: [shopkeeper]

  mineru:
    image: ${ACR_VPC}/mineru-server:1.0.1
    container_name: shopkeeper-mineru
    restart: unless-stopped
    gpus: all
    environment:
      HOME: /root
      MINERU_MODEL_SOURCE: local
      MINERU_API_OUTPUT_ROOT: /data/output
      MINERU_API_TASK_RETENTION_SECONDS: "86400"
      MINERU_API_MAX_CONCURRENT_REQUESTS: "1"
    ports:
      - "8893:80"
    volumes:
      - ./models/mineru:/root
      - ./data/mineru/output:/data/output
    shm_size: 4g
    mem_limit: 8g
    healthcheck:
      test:
        - CMD
        - python
        - -c
        - "import urllib.request; urllib.request.urlopen('http://127.0.0.1/openapi.json', timeout=5)"
      interval: 15s
      timeout: 10s
      retries: 20
      start_period: 60s
    networks: [shopkeeper]

  mineru-gradio:
    image: ${ACR_VPC}/mineru-server:1.0.1
    container_name: shopkeeper-mineru-gradio
    restart: unless-stopped
    command:
      - mineru-gradio
      - --server-name
      - 0.0.0.0
      - --server-port
      - "7860"
      - --api-url
      - http://mineru:80
      - --max-convert-pages
      - "200"
      - --latex-delimiters-type
      - all
    ports:
      - "8895:7860"
    mem_limit: 2g
    depends_on:
      mineru:
        condition: service_healthy
    healthcheck:
      test:
        - CMD
        - python
        - -c
        - "import urllib.request; urllib.request.urlopen('http://127.0.0.1:7860', timeout=5)"
      interval: 15s
      timeout: 10s
      retries: 20
      start_period: 60s
    networks: [shopkeeper]
EOF

chmod 600 compose.gpu.yaml

校验:

docker compose config --quiet
docker compose config --services

服务列表应包含:

etcd
minio
minio-init
milvus
mongodb
neo4j
bge-m3
bge-reranker
mineru
mineru-gradio

22. 启动 GPU 服务

22.1 BGE-M3

docker compose up -d bge-m3
docker compose logs -f bge-m3

看到以下日志后按 Ctrl+C

Model loaded; service ready
docker compose ps bge-m3

预期为 healthy

22.2 Reranker

docker compose up -d bge-reranker
docker compose logs -f bge-reranker

看到模型 backend 启动后按 Ctrl+C

22.3 MinerU API 和 Gradio

docker compose up -d mineru
sleep 20
docker compose up -d mineru-gradio
sleep 20
docker compose ps mineru mineru-gradio
docker compose logs --tail=100 mineru

日志应显示:

Request concurrency limited to 1
Application startup complete

说明:MinerU 3.1.9 没有 /healthz,本方案使用 /openapi.json 做健康检查。


23. GPU 服务接口验收

23.1 BGE-M3 健康和信息

curl -sS http://127.0.0.1:8894/health
curl -sS http://127.0.0.1:8894/info

23.2 Dense 向量

curl -sS http://127.0.0.1:8894/embed \
  -H 'Content-Type: application/json' \
  -d '{"inputs":["万用表如何测量电阻"]}' |
  python3 -c 'import json,sys; x=json.load(sys.stdin); print(len(x), len(x[0]))'

预期:

1 1024

23.3 Sparse 向量

curl -sS http://127.0.0.1:8894/embed_sparse \
  -H 'Content-Type: application/json' \
  -d '{"inputs":["万用表如何测量电阻"]}' |
  python3 -c '
import json, sys
x = json.load(sys.stdin)
print("文本数量:", len(x))
print("非零稀疏特征数:", len(x[0]))
print("前3项:", x[0][:3])
'

非零稀疏特征数大于 0 即通过。

23.4 Reranker

curl -sS http://127.0.0.1:8891/rerank \
  -H 'Content-Type: application/json' \
  -d '{
    "query":"苹果手机",
    "texts":["iPhone 15","红富士苹果","奔驰轿车"],
    "raw_scores":false
  }' | python3 -m json.tool

预期 index: 0 得分最高。Reranker 主要使用相对排序,绝对分数较小不是错误。

23.5 MinerU API

curl -fsS http://127.0.0.1:8893/openapi.json >/dev/null &&
  echo "MinerU API 正常"

Swagger:

http://<ECS_PUBLIC_IP>:8893/docs

Gradio:

http://<ECS_PUBLIC_IP>:8895

23.6 MinerU 三模式验收

在 Gradio 页面上传 1-3 页小 PDF,依次测试:

pipeline
vlm-auto-engine
hybrid-auto-engine

每次测试应满足:

  • 任务提交成功
  • 状态最终为 completed
  • 可以下载结果或看到 Markdown
  • Markdown 有正文
  • MinerU 容器没有重启
  • 没有 CUDA OOM

解析时观察:

watch -n 2 nvidia-smi

已验证的典型状态:

BGE-M3             约 1.2 GiB 显存
Reranker            约 1.3 GiB 显存
MinerU pipeline     约 2.6 GiB 显存增量
三者同时运行        约 5 GiB 总显存

VLM/Hybrid 峰值会明显更高。T4 上必须保持 MinerU 并发为 1。


24. 本地电脑公网连通性验证

nc -vz <ECS_PUBLIC_IP> 19530
nc -vz <ECS_PUBLIC_IP> 27017
nc -vz <ECS_PUBLIC_IP> 7687
nc -vz <ECS_PUBLIC_IP> 9000
nc -vz <ECS_PUBLIC_IP> 9001
nc -vz <ECS_PUBLIC_IP> 8891
nc -vz <ECS_PUBLIC_IP> 8893
nc -vz <ECS_PUBLIC_IP> 8894
nc -vz <ECS_PUBLIC_IP> 8895

浏览器:

MinIO Console:http://<ECS_PUBLIC_IP>:9001
Neo4j Browser:http://<ECS_PUBLIC_IP>:7474
MinerU Swagger:http://<ECS_PUBLIC_IP>:8893/docs
MinerU Gradio:http://<ECS_PUBLIC_IP>:8895

应另外使用一台不在白名单中的网络验证这些端口无法访问。


25. 本地项目 .env

MILVUS_URL=http://<ECS_PUBLIC_IP>:19530
MILVUS_TOKEN=root:<MILVUS_ROOT_PASSWORD>

NEO4J_URI=bolt://<ECS_PUBLIC_IP>:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=<NEO4J_PASSWORD>

MONGO_HOST=<ECS_PUBLIC_IP>
MONGO_PORT=27017
MONGO_USER=shopkeeper-admin
MONGO_PASS=<MONGO_ROOT_PASSWORD>

MINIO_ENDPOINT=<ECS_PUBLIC_IP>:9000
MINIO_ACCESS_KEY=shopkeeper-app
MINIO_SECRET_KEY=<MINIO_APP_PASSWORD>
MINIO_SECURE=false
MINIO_BUCKET=shopkeeper-files

TEI_EMBED_URL=http://<ECS_PUBLIC_IP>:8894
TEI_EMBED_DIM=1024
TEI_RERANK_URL=http://<ECS_PUBLIC_IP>:8891

MINERU_URL=http://<ECS_PUBLIC_IP>:8893
MINERU_DEFAULT_BACKEND=pipeline
MINERU_DEFAULT_LANG=ch

执行项目连接测试:

cd /path/to/shopkeeper_brain
conda activate <PROJECT_CONDA_ENV>
python test_connections.py

<PROJECT_CONDA_ENV> 是本地项目实际使用且已安装 pymilvusneo4jpymongo
miniorequestspython-dotenv 等依赖的 Conda 环境。本仓库当前没有统一的
requirements.txtpyproject.toml,因此基础设施部署文档不假定具体环境名。


26. 日常运维

26.1 查看状态

cd /opt/shopkeeper-stack
docker compose ps
docker stats --no-stream
nvidia-smi
df -h /
docker system df

26.2 查看日志

docker compose logs --tail=200 milvus
docker compose logs --tail=200 bge-m3
docker compose logs --tail=200 bge-reranker
docker compose logs --tail=300 mineru
docker compose logs --tail=200 mineru-gradio

MinerU 解析失败要看 mineru,不是 mineru-gradio。Gradio 只是前端和 API 客户端。

26.3 启停

docker compose stop
docker compose start

单服务:

docker compose restart mineru
docker compose restart bge-m3

26.4 安全清理磁盘

先查看:

docker image ls --filter dangling=true
docker system df

只清理悬空镜像和构建缓存:

docker image prune -f
docker builder prune -f

不要执行:

docker compose down -v
docker system prune --volumes

上述命令可能删除数据卷。


27. 备份与恢复

27.1 必须备份的配置

/opt/shopkeeper-stack/.env
/opt/shopkeeper-stack/compose.yaml
/opt/shopkeeper-stack/compose.gpu.yaml
/opt/shopkeeper-stack/config/
/opt/shopkeeper-stack/scripts/

配置备份:

cd /opt
tar czf /opt/shopkeeper-stack/backups/config-$(date +%F-%H%M%S).tar.gz \
  shopkeeper-stack/.env \
  shopkeeper-stack/compose.yaml \
  shopkeeper-stack/compose.gpu.yaml \
  shopkeeper-stack/config \
  shopkeeper-stack/scripts

27.2 数据备份原则

Milvus 完整恢复至少需要同时保留:

/opt/shopkeeper-stack/data/etcd/data
/opt/shopkeeper-stack/data/minio/data

只备份 MinIO 或只备份 etcd 都不能保证恢复 Milvus。

测试环境最简单的一致性备份方式:

  1. 停止写入任务。
  2. docker compose stop
  3. 创建阿里云系统盘快照。
  4. docker compose start

Neo4j、MongoDB、MinIO 的严格生产级备份应使用各自原生备份工具,本方案不替代生产备份设计。


28. 故障排查记录

28.1 Docker Hub 连接超时

现象:

dial tcp ... registry-1.docker.io:443: i/o timeout

处理:

  • 配置阿里云专属镜像加速器。
  • 第三方命名空间仍可能返回 not found。
  • 对 MongoDB、Neo4j、Milvus、PyTorch、TEI 使用本地 Mac 拉取后推送 ACR。
  • ECS 使用 ACR VPC 地址。

28.2 jq 未安装导致 daemon.json 被空文件覆盖

原因:shell 在执行 jq 前已创建重定向目标,jq 失败后仍执行 mv

恢复:

cp /etc/docker/daemon.json.bak /etc/docker/daemon.json
apt install -y jq

以后必须使用 && 串联校验和覆盖。

28.3 Milvus 循环重启,多个组件争用 19530

日志:

DataCoord fail to create net listener: listen tcp :19530: address already in use
QueryCoord fail to create net listener
Proxy fail to create external grpc listener
panic: context canceled

原因:把局部配置挂载为完整 /milvus/configs/milvus.yaml,覆盖镜像默认端口配置。

修复:局部配置命名为 user.yaml,挂载到:

/milvus/configs/user.yaml

不要删除 etcd、MinIO 或 Milvus 数据目录。

28.4 MinerU 构建 stringzilla 失败

日志:

error: command 'gcc' failed: No such file or directory
Failed building wheel for stringzilla

修复:Dockerfile 安装 build-essential

28.5 MinerU 自动升级到非预期版本

问题配置:

mineru[core]>=3.1.9,<4

可能解析到 3.4.x,并引入不同依赖。修复为:

mineru[core]==3.1.9

28.6 PyTorch 2.4 wheel 下载超时

旧 Dockerfile 在安装 MinerU 后又从 download.pytorch.org 下载 799 MB Torch 2.4 wheel,跨境网络超时。

本次新服务器 driver 580 支持 CUDA 13,MinerU 3.1.9 安装的 torch 2.13.0+cu130 已通过 T4 验证,因此删除旧的强制降级步骤。

28.7 MinerU 解析报 torchvision.extension

日志:

partially initialized module 'torchvision' has no attribute 'extension'

原因:

torch 2.13.0+cu130
torchvision 0.19.0

二进制不兼容。修复为:

torchvision 0.28.0

必须验证:

torchvision.extension._has_ops() is True

28.8 MinerU /healthz 返回 404

MinerU 3.1.9 没有 /healthz。使用:

/openapi.json

作为 Compose 健康检查。

28.9 Gradio 页面报错但 Gradio 没有日志

Gradio 只是调用 MinerU API。后端解析异常查看:

docker compose logs --tail=300 mineru

28.10 docker compose logs -f 被暂停

Ctrl+Z 会把日志进程挂起并保留 shell job。正确退出使用 Ctrl+C

清理挂起 job:

jobs
kill %1

28.11 MinerU 并发稳定性

MinerU 3.1.x 的 pipeline/native 依赖在并发任务下可能发生原生进程崩溃。单卡测试环境统一设置:

MINERU_API_MAX_CONCURRENT_REQUESTS=1

VLM 和 Hybrid 也不应在 T4 上并发执行。


29. 完整验收清单

  • Ubuntu 22.04、时区、NTP 正常
  • 8 GiB Swap 生效
  • nvidia-smi 显示 Tesla T4
  • 普通 Ubuntu 容器内可执行 nvidia-smi
  • Docker Hub 加速器与 NVIDIA runtime 同时保留
  • ACR 公网/VPC 登录正常
  • MinIO 两个 bucket 和两个受限账号已创建
  • MongoDB 认证 ping 成功
  • Neo4j RETURN 1 成功
  • etcd healthy 且未开放公网
  • Milvus /healthz 返回 OK
  • Milvus 带 token 列 collection 成功
  • BGE-M3 /embed 返回 1024 维 dense
  • BGE-M3 /embed_sparse 返回非空 sparse
  • Reranker 将 iPhone 15 排在 index 0
  • MinerU API healthy
  • MinerU Gradio 页面可访问
  • MinerU pipeline PDF 解析成功
  • MinerU vlm-auto-engine PDF 解析成功
  • MinerU hybrid-auto-engine PDF 解析成功
  • 本地白名单 IP 可连接所有对外端口
  • 非白名单网络不能访问对外端口
  • 已创建系统盘快照
  • .env 已进入密码管理器且未提交仓库

30. 参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值