linux服务器部署DeepSeek Harness 并调用本地LLM全过程总结
一、环境现状
| 项 | 值 |
|---|
| 宿主机 | bigdata-55,内网 10.0.3.55 |
| 系统 | CentOS 7(内核 3.10,el7) |
| 容器 | Docker,node:22 镜像 |
| 模型服务 | 10.0.24.10:8001,vLLM 部署 Qwen3-32B |
| 模型硬件 | 单张 A800 80GB,已用 71/80 GB |
| 对外访问 | nginx 监听 0.0.0.0:9090 → 反代容器内 127.0.0.1:3080 |
二、踩过的坑(按顺序)
阶段 1:装 Node.js
| # | 坑 | 原因 | 解决 |
|---|
| 1 | setup_lts.x 报 “only supported on Debian-based systems” | CentOS 7 是 RHEL 系,不能用 Debian 脚本 | 换 RPM 脚本或直接下二进制 |
| 2 | NodeSource RPM 脚本装 Node 24 失败,报 glibc >= 2.28 | CentOS 7 glibc 只有 2.17,el7 无法升级 | CentOS 7 上无法装 Node 20+ 官方包 |
| 3 | 降到 Node 18 能用,但 dsh 要求 Node 22.19+ / 24+ | 版本不匹配 | 只能上 Docker,容器内 glibc 独立 |
阶段 2:Docker 起 dsh
| # | 坑 | 原因 | 解决 |
|---|
| 4 | dsh web 拒绝 --host 0.0.0.0 | 官方安全设计:Web UI 能执行代码,暴露到网络等于 RCE | 只能绑 127.0.0.1,外部访问靠反向代理 |
| 5 | 从别的机器访问 10.0.3.55:3080 被拒 | dsh 默认绑 127.0.0.1 | 用 nginx/socat 转发 |
| 6 | 配置写在宿主机 .dsh,容器读不到 | 容器默认不挂 .dsh | 启动时加 -v /root/.dsh:/root/.dsh |
阶段 3:nginx 反代
| # | 坑 | 原因 | 解决 |
|---|
| 7 | nginx 起不来,bind() to 0.0.0.0:9090 failed (Permission denied) | SELinux 只允许 nginx 绑白名单端口 | semanage port -a -t http_port_t -p tcp 9090 |
| 8 | 502 Bad Gateway,日志 connect() to 127.0.0.1:3080 failed (13: Permission denied) | SELinux 默认禁止 nginx 外连其他端口 | setsebool -P httpd_can_network_connect 1 |
| 9 | 403 Forbidden / trust fence 报错 | nginx 改写 Host 后,dsh 校验不过 | 用 proxy_set_header Host $http_host; 透传原始 Host |
| 10 | Cookie 里记录的 authority 是旧的 127.0.0.1:3080,与访问地址冲突 | 之前用 SSH 隧道留下的旧 Cookie | 清浏览器 Cookie 或无痕窗口 |
| 11 | settings are unavailable in this browser | 客户端 JS 校验 window.location.host | 装 dsh-web-lan-access 插件解决 |
阶段 4:接本地 Qwen
| # | 坑 | 原因 | 解决 |
|---|
| 12 | no credential for provider route "qwen-local" | dsh 强制要求每个 provider 有凭据引用 | 装 dsh-key-manager,或在 UI 里填占位 Key |
| 13 | 400 status code (no body) | dsh 发送 developer role / max_completion_tokens,vLLM 不认 | 加 compat 配置 + 装 dsh-localqwen-rolefix |
| 14 | context-overflow compaction failed | 上下文窗口填了 256k,远超 vLLM 的 32k | UI 里改成 32768 |
| 15 | 装了 dsh-llm-qwen-local 后,地址被自动改成 127.0.0.1:8000 | 插件有默认配置,优先级高于 settings.yaml | 用 cordis.patch.yml 通过 id: llm-qwen-local 整体覆盖 |
| 16 | 插件 patch 不生效 | patch 是整体替换,不是深度合并 | 所有字段都要重写一遍 |
| 17 | Agent 调用 ping 失败 | node:22 容器是精简镜像,没装 ping | 容器内 apt install iputils-ping,或写进 Dockerfile |
三、最终可用配置
1. 容器启动命令
docker run -d --name dsh \
--network host \
--restart unless-stopped \
-v /root/deepseek-harness:/app \
-v /root/.dsh:/root/.dsh \
-w /app \
node:22 \
bash -c "apt update && apt install -y iputils-ping curl net-tools dnsutils iproute2 procps && npx @deepseek-ai/dsh web --no-open --trusted-host 10.0.3.55:9090"
2. /root/.dsh/profiles/web/cordis.patch.yml
- id: llm-qwen-local
config:
baseURL: http://10.0.24.10:8001/v1
models:
- id: /home/model/Qwen3-32B
name: Qwen3-32B
contextWindow: 32768
maxTokens: 4096
multimodal: false
reasoning:
efforts:
- { id: off, wire: none }
defaultEffort: off
3. /root/.dsh/settings.yaml
agent-default-model:
provider: qwen-local
model: /home/model/Qwen3-32B
reasoningEffort: off
4. nginx /etc/nginx/conf.d/dsh.conf
server {
listen 0.0.0.0:9090;
server_name _;
location / {
proxy_pass http://127.0.0.1:3080;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
}
5. vLLM 启动参数(Qwen 那台机器)
vllm serve /home/model/Qwen3-32B \
--tokenizer /home/model/Qwen3-32B \
--tensor-parallel-size 1 \
--max-model-len 32768 \
--gpu-memory-utilization 0.92 \
--dtype bfloat16 \
--kv-cache-dtype fp8 \
--max-num-seqs 4 \
--port 8001 \
--enable-auto-tool-choice \
--tool-call-parser hermes
四、几个核心认知
- CentOS 7 跑不了现代 Node —— glibc 2.17 是死结,Docker 是唯一出路。
- dsh 拒绝
0.0.0.0 是有意为之 —— Web UI 能执行代码,暴露到网络 = RCE,所以只能反代。 - SELinux 是 CentOS 7 上最坑的一环 —— 端口绑定、外连、文件访问都可能被拦,遇到
Permission denied 先想它。 - 插件有默认配置,会覆盖 settings.yaml —— 要用
cordis.patch.yml 按 id 整体覆盖。 - patch 是整体替换 —— 不是深度合并,每个字段都要重写。
- 容器是精简镜像 —— Agent 要用的命令得自己装。
- 32k 上下文是硬件上限 —— A800 80GB 跑 32B 模型,KV cache 空间只剩 ~10GB,调大就 OOM。
- vLLM 的
--tool-call-parser 是工具调用的硬门槛 —— 没有它,插件配得再对也不行。
五、当前状态
✅ dsh 在 Docker 里稳定运行
✅ 内网通过 http://10.0.3.55:9090/?token=... 访问
✅ 已接通本地 Qwen3-32B,支持对话和 Agent 工具调用
✅ 容器内已装常用命令(ping、curl 等)
⚠️ vLLM 未加 --reasoning-parser qwen3,思考内容混在正文里
⚠️ 上下文窗口锁 32k,受显存限制无法调大
所有评论(0)