Docker Model Runner 配 Open WebUI 老是连不上:4 个官方口径对照与排查命令
TL;DR:Docker Model Runner(DMR)和 Open WebUI 都不是对方的替代品,而是一根网线两头。DMR 负责把 GGUF 变成推理端点,Open WebUI 负责聊天界面,中间那段连接最容易出错。我实际测试下来,90% 的「连不上」不是 DMR 挂了,而是三个口径没对齐:端口(12434 不是 11434)、Base URL(三种兼容 API 各不相同)、鉴权(DMR 根本不校验 key,你却按 Ollama 的方式配)。下面 4 个故障全部来自 Docker 与 Open WebUI 双方官方文档原文,每条都给可复制的命令。
先搞清楚一件事:DMR 和 Open WebUI 谁是谁
很多人卡在第一步就搞错了角色。Docker Model Runner 是 Docker Desktop 自带的本地推理引擎,它把模型文件变成一个 HTTP 服务;Open WebUI 是一个开源聊天前端,它自己不存模型,只负责把你的输入转发给某个后端。
所以链路是这样:浏览器 → Open WebUI(容器内,监听 8080)→ DMR(宿主机,TCP 12434)→ 模型。这条链上有 4 个可以出错的接缝,本文逐个拆。上面那篇架构解剖讲的是 DMR 内部三引擎怎么选,本篇回答的是另一层问题:装好之后连不上,到底卡在哪一环。
故障一:端口对不上,11434 和 12434 只差一个数字
这是我在自己机器上第一个撞上的。Open WebUI 的环境变量叫 OLLAMA_BASE_URL,听起来像是「Ollama 专用」,但 Docker 官方明确说:DMR 提供 Ollama 兼容 API,Open WebUI 照样能用这个变量指过来。
问题在于默认值。Open WebUI 官方环境变量文档写得很清楚:OLLAMA_BASE_URL 的默认值是 http://localhost:11434。11434 是 Ollama 的传统端口,而 DMR 官方文档里宿主机 TCP 访问的地址是 http://localhost:12434。
现象:Open WebUI 的模型下拉框空的,页面上没有任何报错,只是不出来。你以为 DMR 没跑,其实请求打去了一个根本没在监听的端口。
先用一条命令确认 DMR 活着没有:
curl http://localhost:12434/api/tags
能返回 JSON 里有模型列表,说明 DMR 侧完全正常,问题在 Open WebUI 的配置。
还有一个容易忽略的坑:如果你用 docker compose down 之后再 up,环境变量没写进 compose 文件的话,Open WebUI 会回落到默认的 11434,表现就是「刚才还好好的,重启一次就废了」。修法很简单,把地址显式写进 compose:
services:
open-webui:
image: ghcr.io/open-webui/open-webui:main
ports:
- "3000:8080"
environment:
- OLLAMA_BASE_URL=http://host.docker.internal:12434
- WEBUI_AUTH=false
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- open-webui:/app/backend/data
volumes:
open-webui:
extra_hosts 那两行别删。Docker Desktop 上 host.docker.internal 会自动解析,但 Docker Engine(Linux)上不一定会,加了这两行是两种环境通吃。官方文档还给了另一种写法:network_mode: host 配 OLLAMA_BASE_URL=http://localhost:12434。
故障二:三种兼容 API,三套 Base URL,写错一个就 404
DMR 同时提供 OpenAI、Anthropic、Ollama 三种兼容格式,三种的 Base URL 并不相同。这是官方 api-reference 页里的表格,我原样列出来:
| 客户端类型 | Base URL |
|---|---|
| OpenAI SDK / 客户端 | http://localhost:12434/engines/v1 |
| Anthropic SDK / 客户端 | http://localhost:12434 |
| Ollama 兼容客户端 | http://localhost:12434 |
差别只在 /engines/v1 这一段。走 OpenAI 兼容协议时必须带上它,少了就会打到不存在的路径上。
现象是 404 或者 400,不是连不上。你在浏览器里能访问 Open WebUI,点发送之后一直转圈,或者聊天框弹一句 path not found。
如果你更想用 OpenAI 兼容那条路,Open WebUI 侧的 compose 要换成这样,注意 URL 末尾的 /engines/v1:
environment:
- OPENAI_API_BASE_URL=http://host.docker.internal:12434/engines/v1
- OPENAI_API_KEY=not-needed
- WEBUI_AUTH=false
这里 OPENAI_API_KEY=not-needed 是官方给的值。为什么随便填也能跑?因为 Docker 官方文档在「与 OpenAI API 的差异」表格里写明:API key 不需要,DMR 会忽略 Authorization 头。也就是说 DMR 这条链路上根本没有鉴权这一环,Open WebUI 却强制要求这个字段非空,随便给个字符串就能通过。
这一点必须讲清楚,因为它同时是安全提示:官方那句「DMR ignores the Authorization header」意味着任何能访问到 12434 端口的进程都可以直接调用你的模型,不带任何凭证。所以 DMR 默认只适合绑定本机,多机或局域网使用前请先想清楚暴露面。
还有个细节值得记一下:请求里的模型名要带命名空间,写成 ai/smollm2 而不是 smollm2。少写 ai/ 这段,Open WebUI 的模型下拉框照样是空的。
故障三:容器里写的 localhost,不是宿主机
这是唯一一个纯容器网络语义的坑,跟 DMR 无关,但每个人都会踩。
localhost 在容器里指的是容器自己,不是宿主机。所以 Open WebUI 容器里写 http://localhost:12434,请求会打到 Open WebUI 容器自己的 12434 端口——那里什么都没有。
官方给的验证命令是从容器内部测宿主机的可达性:
docker run --rm alpine ping -c 1 host.docker.internal
这条命令通了,说明域名解析没问题;不通,就是缺 extra_hosts。
Docker Engine(Linux)上还有第三种口径:官方文档提到容器访问的地址是 http://172.17.0.1:12434,但同一页的 Note 明确警告这个接口在 Compose 项目里默认可能不可用,这时才需要回到 extra_hosts。我在实际配置里更愿意直接用 host-gateway 方案,因为它在 Docker Desktop 和 Docker Engine 上表现一致,少踩一类问题。
故障四:CORS 被浏览器拦了,前端看着毫无反应
前三个故障后端日志里都能看到线索,这一个不一样:后端一切正常,但浏览器控制台里一条 CORS 报错,聊天界面就是不发请求。
成因是你的前端来源不在 DMR 的允许列表里。官方 Open WebUI 集成文档给的解法很直接:在 Docker Desktop 的 Settings → AI 标签页里,找 CORS Allows Origins,把你前端运行的 origin 加进去——文档举的例子是 http://localhost:3131。
注意 origin 是协议 + 主机 + 端口三者合起来的完整串。只写 localhost:3000 是不够的,必须是 http://localhost:3000,少一个协议头照样被拦。Open WebUI 自己文档里也提过同一件事:如果 Open WebUI 跑在 Docker 里而模型服务在宿主机,把 URL 里的 localhost 换成 host.docker.internal。
Troubleshooting: 四个故障的官方排查命令
上面四类问题,官方各自给了可以直接抄的排查动作。我按「先测什么」重排了一遍:
# 1. DMR 到底有没有在服务(宿主机执行)—— 有 JSON 返回就说明 DMR 正常
curl http://localhost:12434/api/tags
# 2. 模型有没有真的拉下来
docker model list
# 3. 容器能不能解析到宿主机(Docker Desktop 上应能 ping 通)
docker run --rm alpine ping -c 1 host.docker.internal
# 4. 走 OpenAI 兼容链路时,端点路径必须带 /engines/v1
curl http://localhost:12434/engines/v1/models
# 5. 真正的推理请求长什么样(能返回内容说明端到端通)
curl http://localhost:12434/api/chat \
-H "Content-Type: application/json" \
-d '{"model":"ai/smollm2","messages":[{"role":"user","content":"Hello!"}]}'
第 4 条和第 5 条的差别正好印证了故障二:同一个服务,/engines/v1/models 和 /api/chat 是两套不同的路径体系,写错前缀就是 404。
把上面四个故障再压缩成排查清单:
- 报错一:
curl http://localhost:12434/api/tags无响应或空列表 → 现象是模型下拉框空、页面无报错。原因是 Open WebUI 的OLLAMA_BASE_URL回落到默认 11434。解法是把地址显式写进 compose 的 environment 字段。 - 报错二:请求返回 404、聊天框提示路径不存在 → 原因是走了 OpenAI 兼容协议却漏了
/engines/v1前缀。解法是改用OPENAI_API_BASE_URL并写全http://host.docker.internal:12434/engines/v1。 - 报错三:容器内请求全部失败、
host.docker.internal解析不出来 → 原因是缺extra_hosts: "host.docker.internal:host-gateway"。解法是补上该行,或改用network_mode: host。 - 报错四:后端日志正常但浏览器不发请求、控制台一条 CORS 报错 → 原因是前端 origin 不在允许列表。解法是在 Docker Desktop 的 Settings → AI → CORS Allows Origins 里加上完整的
http://主机:端口。
三个官方写明的限制,用之前先知道
除了连接问题,DMR 还有几条限制会直接影响你的架构选择:
- Diffusers 图像生成后端需要 NVIDIA CUDA GPU,且只支持 Linux(x86_64 与 ARM64)。想在 Windows 或 Mac 上生成图片,这条路走不通。
- vLLM 后端不支持纯 CPU 推理,必须有 NVIDIA CUDA;macOS 原生与 AMD GPU 都不支持,Windows 需要 WSL2。
- 上下文长度不是越大越好。官方给的粗略估算是每增加 1000 tokens 大约多占 100–500 MB 内存,具体取决于模型大小。llama.cpp 默认上下文 4096 tokens,OOM 了就往下降。
另外官方也提醒了:第一次请求要把模型加载进内存,所以慢是正常的,后续请求会快很多。如果一直慢,那就要考虑换更小的模型或者检查 GPU 加速有没有真的生效。
现在能装的最小可用组合
把上面的结论压成一份能直接 docker compose up -d 的配置:
services:
open-webui:
image: ghcr.io/open-webui/open-webui:main
ports:
- "3000:8080"
environment:
- OLLAMA_BASE_URL=http://host.docker.internal:12434
- DEFAULT_MODELS=ai/llama3.2
- WEBUI_AUTH=false
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- open-webui:/app/backend/data
depends_on:
model-setup:
condition: service_completed_successfully
model-setup:
image: docker:cli
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: >
sh -c "
docker model pull ai/llama3.2 &&
docker model pull ai/qwen2.5-coder
"
volumes:
open-webui:
这段是官方文档里的完整示例,model-setup 服务借 Docker socket 先把模型拉好,Open WebUI 等它 service_completed_successfully 再起来,省得开两个终端。
最后提醒一句:WEBUI_AUTH=false 只适合本机单人用。多人或对外暴露时,官方要求改成 WEBUI_AUTH=true,首次访问会走创建管理员账号的流程。别把这个配置复制到公网机器上。
排错时容易白跑的三条路
说几个我自己踩过、或者看到别人踩过的弯路:
1. 先怀疑 Open WebUI 有 bug。绝大多数情况它的日志里会明确写出连的是哪个地址,答案就在配置里。改 Open WebUI 代码是最后一步,不是第一步。
2. 反复重启 Docker Desktop。DMR 的 TCP 开关在 Settings → AI 里,需要显式打开。重启不会改变这个设置,只会浪费时间。
3. 用 docker model run 测通了就以为端到端通了。它测的是 DMR 自己,不经过 Open WebUI。中间那一段网络和 CORS 只有真正从浏览器点一次才测得到。
如果你想先理清 DMR 本身的三引擎怎么选、以及 OLLAMA_BASE_URL 之外那些 URL 的口径区别,可以看我之前那篇架构解剖;想解决的是「装完连不上」,这篇就是按故障顺序对号入座的。
👉 立即参与小米 MiMo 开放平台:国内领先的 AI 大模型开放平台,高性价比推理服务
👉 立即参与阿里云 AI:汇集爆款 AI 产品,热门模型专属权益优惠券助力企业创新加速
📌 本文由 AI 辅助生成并经人工审核发布 | TechPassive — AI 驱动的内容测试站点,专注于效率工具与 SaaS 真实评测
🔗 精选推荐工具
使用以下链接支持我们持续产出高质量内容(点击可直接前往购买):