网络技巧
本指南介绍如何在不修改代码库文件的情况下,在受限或缓慢的网络环境中构建和运行。您将通过使用小型本地覆盖文件和 compose 覆盖配置,从而保持代码库的整洁。
解决的问题
- Hugging Face 模型下载被拦截或缓慢
- Docker 构建期间 Go 模块获取被拦截
- mock-vLLM 测试镜像的 PyPI 访问问题
摘要:选择您的方案
- 最快且最可靠:使用
./models中的本地模型,完全跳过 HF 网络。 - 否则:通过 compose 覆盖配置挂载 HF 缓存并设置镜像站环境变量。
- 构建时:使用覆盖 Dockerfile 设置 Go 镜像(提供示例)。
- 针对 mock-vllm:使用覆盖 Dockerfile 设置 pip 镜像(提供示例)。
您可以根据具体情况混合使用这些方法。
1. Hugging Face 模型
除非您提供本地模型,否则路由器会在首次运行时下载嵌入模型。如果可能,首选方案 A。
方案 A — 使用本地模型(无需外部网络)
-
通过任何可行的方法(VPN/离线)将所需的模型下载到代码库的
./models文件夹中。示例布局:models/all-MiniLM-L12-v2/models/category_classifier_modernbert-base_model
-
在
config/config.yaml中指向本地路径。示例:bert_model:
# point to a local folder under /app/models (already mounted by compose)
model_id: /app/models/all-MiniLM-L12-v2 -
不需要额外的环境变量。
deploy/docker-compose/docker-compose.yml已经挂载了./models:/app/models:ro。
方案 B — 使用 HF 缓存 + 镜像站
创建一个 compose 覆盖文件以持久化缓存并使用区域镜像站(以下示例使用中国镜像站)。在代码库根目录保存为 docker-compose.override.yml(当您同时指定两者时,Compose 会自动将其与 deploy/docker-compose/docker-compose.yml 合并):
services:
semantic-router:
volumes:
- ~/.cache/huggingface:/root/.cache/huggingface
environment:
- HUGGINGFACE_HUB_CACHE=/root/.cache/huggingface
- HF_HUB_ENABLE_HF_TRANSFER=1
- HF_ENDPOINT=https://hf-mirror.com # example mirror endpoint (China)
可选:在宿主机上预热缓存(仅当您安装了 huggingface_hub 时):
python -m pip install -U huggingface_hub
python - <<'PY'
from huggingface_hub import snapshot_download
snapshot_download(repo_id="sentence-transformers/all-MiniLM-L6-v2", local_dir="~/.cache/huggingface/hub/models--sentence-transformers--all-MiniLM-L6-v2")
PY
2. 使用 Go 镜像构建(Dockerfile 覆盖)
构建 tools/docker/Dockerfile.extproc 时,Go 阶段可能会卡在 proxy.golang.org。创建一个启用镜像站的覆盖 Dockerfile,而无需改动原始文件。
- 创建
tools/docker/Dockerfile.extproc.cn,内容如下:
# syntax=docker/dockerfile:1
FROM rust:1.90 AS rust-builder
RUN apt-get update && apt-get install -y make build-essential pkg-config && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY tools/make/ tools/make/
COPY Makefile ./
COPY candle-binding/Cargo.toml candle-binding/
COPY candle-binding/src/ candle-binding/src/
RUN make rust
FROM golang:1.24 AS go-builder
WORKDIR /app
# Go module mirrors (example: goproxy.cn)
ENV GOPROXY=https://goproxy.cn,direct
ENV GOSUMDB=sum.golang.google.cn
RUN mkdir -p src/semantic-router
COPY src/semantic-router/go.mod src/semantic-router/go.sum src/semantic-router/
COPY candle-binding/go.mod candle-binding/semantic-router.go candle-binding/
# Pre-download modules to fail fast if mirrors are unreachable
RUN cd src/semantic-router && go mod download && \
cd /app/candle-binding && go mod download
COPY src/semantic-router/ src/semantic-router/
COPY --from=rust-builder /app/candle-binding/target/release/libcandle_semantic_router.so /app/candle-binding/target/release/
ENV CGO_ENABLED=1
ENV LD_LIBRARY_PATH=/app/candle-binding/target/release
RUN mkdir -p bin && cd src/semantic-router && go build -o ../../bin/router cmd/main.go
FROM quay.io/centos/centos:stream10
WORKDIR /app
COPY --from=go-builder /app/bin/router /app/extproc-server
COPY --from=go-builder /app/candle-binding/target/release/libcandle_semantic_router.so /app/lib/
COPY config/config.yaml /app/config/
ENV LD_LIBRARY_PATH=/app/lib
EXPOSE 50051
COPY scripts/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]
- 通过扩展
docker-compose.override.yml将 compose 指向覆盖 Dockerfile:
services:
semantic-router:
build:
dockerfile: tools/docker/Dockerfile.extproc.cn
3. Mock vLLM (通过 Dockerfile 覆盖设置 PyPI 镜像站)
对于可选的测试配置(profile),创建一个覆盖 Dockerfile 以配置 pip 镜像站。
- 创建
tools/mock-vllm/Dockerfile.cn:
FROM python:3.11-slim
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
# Pip mirror (example: TUNA mirror in China)
RUN python -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && \
python -m pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn
COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py /app/app.py
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
- 扩展
docker-compose.override.yml,以便为mock-vllm使用覆盖 Dockerfile:
services:
mock-vllm:
build:
dockerfile: Dockerfile.cn
4. 构建并运行
完成覆盖配置后,正常进行构建和运行(Compose 会自动合并):
# Build all images with overrides (explicitly reference the relocated compose file)
docker compose -f deploy/docker-compose/docker-compose.yml -f docker-compose.override.yml build
# Run router + envoy
docker compose -f deploy/docker-compose/docker-compose.yml -f docker-compose.override.yml up -d
# If you need the testing profile (mock-vllm)
docker compose -f deploy/docker-compose/docker-compose.yml -f docker-compose.override.yml --profile testing up -d
5. 出口受限的 Kubernetes 集群
Kubernetes 节点上的容器运行时不会自动重用宿主机的 Docker 守护进程设置。当注册表访问缓慢或被拦截时,Pod 可能会处于 ImagePullBackOff 状态。请选择或组合使用以下缓解措施:
5.1 配置 containerd 或 CRI 镜像站
- 对于基于 containerd 的集群(如 Kind、k3s、kubeadm),编辑
/etc/containerd/config.toml或使用 Kind 的containerdConfigPatches,为docker.io、ghcr.io或quay.io等注册表添加区域镜像站端点。 - 更改后重启 containerd 和 kubelet,使新镜像站生效。
- 除非每个节点都能访问该代理地址,否则避免将镜像站指向回环代理(loopback proxies)。
5.2 预加载或侧载镜像
- 在本地构建所需的镜像,然后将其推送到集群运行时。对于 Kind,运行
kind load docker-image --name <cluster> <image:tag>;对于其他集群,在每个节点上使用crictl pull或ctr -n k8s.io images import。 - 当您确定镜像已存在于节点上时,修改 Deployment 将
imagePullPolicy设置为IfNotPresent。
5.3 发布到可访问的注册表
- 为镜像打标签并推送到可从集群访问的注册表(云提供商注册表、私有托管的 Harbor 等)。
- 使用新的镜像名称更新您的
kustomization.yaml或 Helm values,如果注册表需要身份验证,请配置imagePullSecrets。
5.4 运行本地拉取穿透缓存
- 在同一网络内启动注册表代理(
registry:2或供应商特定的缓存),在 containerd 中将其配置为镜像站,并定期预热您需要的镜像。
5.5 调整后验证
- 使用
kubectl describe pod <name>或kubectl get events确认拉取错误已消失。 - 检查诸如
semantic-router-metrics之类的服务是否已暴露端点,并能通过端口转发进行响应(kubectl port-forward svc/<service> <local-port>:<service-port>)。
6. 故障排除
-
Go 模块仍然超时
- 检查 go-builder 阶段的日志中是否存在
GOPROXY和GOSUMDB。 - 尝试清理构建:
docker compose build --no-cache。
- 检查 go-builder 阶段的日志中是否存在
-
HF 模型下载仍然缓慢
- 首选方案 A(本地模型)。
- 确保已挂载缓存卷,并且设置了
HF_ENDPOINT/HF_HUB_ENABLE_HF_TRANSFER。
-
mock-vllm 的 PyPI 速度慢
- 确认该服务正在使用指定的 CN Dockerfile。