这次想在测试机上跑一个 Open WebUI,给团队内部搭个连 Ollama 的入口。镜像本身不算复杂,官方主镜像是 ghcr.io/open-webui/open-webui:main,但真正排查问题的时候会发现,坑通常分三层:镜像拉取、容器网络、数据卷。

先把镜像层单独过掉
GHCR 拉取不稳定时,先别急着写 compose。单独拉一下镜像:
docker pull ghcr.1ms.run/open-webui/open-webui:main
先让镜像层过去,后面再单独看 WebUI 和 Ollama 之间的连接。否则的话,docker compose up 一跑起来,所有问题就会混在一起,让人头大。
最小 Compose
我们来看一个最小版本的 Compose 配置:
services:
open-webui:
image: ghcr.1ms.run/open-webui/open-webui:main
container_name: open-webui
restart: unless-stopped
ports:
- "3000:8080"
environment:
OLLAMA_BASE_URL: "https://host.docker.internal:11434"
volumes:
- open-webui:/app/backend/data
volumes:
open-webui:
然后启动:
docker compose pull
docker compose up -d
docker compose logs -f open-webui
第一个坑:容器里的 localhost 不是宿主机
Ollama 如果跑在宿主机上,WebUI 容器里直接用 127.0.0.1:11434 去访问,实际上访问到的是容器自己,这就尴尬了。
所以正确做法是用:
environment:
OLLAMA_BASE_URL: "https://host.docker.internal:11434"
如果 Linux 上这个地址不可用,可以试试:
extra_hosts:
- "host.docker.internal:host-gateway"
或者干脆把 Ollama 也放到同一个 compose 网络里,让 Open WebUI 直接访问 https://ollama:11434,省心很多。
第二个坑:数据卷必须提前想好
Open WebUI 的数据路径是 /app/backend/data,所以 compose 里一定要配上:
volumes:
- open-webui:/app/backend/data
没有这个卷,容器重建后配置就可能全部丢失。自托管服务最烦人的不是第一次启动,而是升级之后发现数据没按预期保留下来。
第三个坑:端口和安全组
容器启动不代表外部就能访问了。你得先确认端口映射和日志都没问题:
docker ps -lntp | grep 3000
docker logs open-webui
如果是云服务器,还要检查安全组有没有放开 3000 端口。如果前面挂了反向袋里,再看看 Nginx upstream 指向的是宿主机的端口还是容器网络地址。
排查表
| 问题 | 命令 |
|---|---|
| 镜像是否能拉 | docker pull ghcr.1ms.run/open-webui/open-webui:main |
| 容器是否在跑 | docker ps | grep open-webui |
| 日志是否异常 | docker logs -f open-webui |
| Ollama 是否可访问 | curl https://127.0.0.1:11434/api/tags |
| 数据卷是否存在 | docker volume inspect open-webui |
结论
用 Docker 部署 Open WebUI 并不复杂,真正的难点在于把“镜像、端口、Ollama 地址、数据卷”这几层分开排查。团队内网 AI 入口要长期稳定运行,Compose 文件、数据卷管理和升级路径的规划,远比第一次启动时的顺利重要得多。
