Docker Model Runner Won't Connect to Open WebUI: 4 Official Fixes
TL;DR: Docker Model Runner (DMR) and Open WebUI are not substitutes for each other. They are the two ends of one network cable. DMR turns model files into an inference endpoint; Open WebUI is the chat interface in front of it. I tested this setup myself, and almost every "can't connect" failure was not DMR being down. It was three things not lining up: the port (12434, not 11434), the base URL (the three compatibility APIs each need a different one), and auth (DMR does not check keys at all, yet you configure it as if it were Ollama). All four failures below come from the official Docker and Open WebUI documentation, and every one comes with a command you can copy and run.
First: what DMR and Open WebUI actually are
A lot of people get the roles backwards on the first step. Docker Model Runner is the local inference engine that ships with Docker Desktop. It takes a model file and exposes it as an HTTP service. Open WebUI is an open-source chat frontend. It stores no models itself. It forwards what you type to some backend.
So the chain is: browser to Open WebUI (inside a container, listening on 8080), then to DMR (on the host, TCP 12434), then to the model. There are four seams along that chain where it can break, and this post walks them one at a time. If you want to know how the three inference engines differ, that is a different layer; what this post answers is the layer above it: everything is installed, and now nothing connects.
Failure 1: the port is 12434, not 11434
This was the first one I hit on my own machine. Open WebUI's environment variable is called OLLAMA_BASE_URL, which sounds like it must be Ollama-only. But Docker's own documentation is explicit: DMR provides an Ollama-compatible API, and Open WebUI can point this variable at it just fine.
The problem is the default value. The Open WebUI environment variable documentation states the default for OLLAMA_BASE_URL is http://localhost:11434. Port 11434 is Ollama's traditional port. Docker's DMR documentation gives the host-side TCP address as http://localhost:12434.
What you see: the model drop-down in Open WebUI is empty. No error message anywhere on the page. You assume DMR never started, when in reality the requests are going to a port where nothing is listening.
Check whether DMR is alive with one command:
curl http://localhost:12434/api/tags
If you get JSON containing a model list, DMR is completely healthy and the problem is in Open WebUI's configuration.
There is a second trap here: after a docker compose down followed by up, if the environment variable is not in your compose file, Open WebUI falls back to the 11434 default. The symptom reads as "it worked a minute ago and a restart ruined it." The fix is simply to write the address explicitly:
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:
Do not delete those extra_hosts lines. On Docker Desktop, host.docker.internal resolves automatically. On Docker Engine on Linux it may not, and keeping both lines makes the same file work in either environment. The official docs also offer a second form: network_mode: host together with OLLAMA_BASE_URL=http://localhost:12434.
Failure 2: three compatibility APIs, three base URLs
DMR exposes OpenAI, Anthropic, and Ollama compatible formats at the same time, and their base URLs are not the same. This is the table from the official API reference page, reproduced as written:
| Client type | Base URL |
|---|---|
| OpenAI SDK / clients | http://localhost:12434/engines/v1 |
| Anthropic SDK / clients | http://localhost:12434 |
| Ollama-compatible clients | http://localhost:12434 |
The only difference is the /engines/v1 segment. If you are speaking the OpenAI-compatible protocol, that suffix is required. Leave it off and your request hits a path that does not exist.
The symptom is a 404 or a 400, not a connection failure. You can load Open WebUI in the browser, you click send, and it either spins forever or the chat box reports a path not found.
If you would rather use the OpenAI-compatible route, the Open WebUI service in your compose file becomes this, with note the trailing /engines/v1:
environment:
- OPENAI_API_BASE_URL=http://host.docker.internal:12434/engines/v1
- OPENAI_API_KEY=not-needed
- WEBUI_AUTH=false
That OPENAI_API_KEY=not-needed value is what the official docs use. Why does any string work? Because Docker's documentation, in its table of differences from the OpenAI API, states plainly that an API key is not required and that DMR ignores the Authorization header. In other words there is no authentication step at all on this path, yet Open WebUI insists the field be non-empty, so any placeholder passes.
This deserves to be spelled out because it is also a security note. That official line about ignoring the Authorization header means any process that can reach port 12434 can call your model with no credentials at all. DMR is designed to bind locally. Think carefully about your exposure before putting it on a LAN or a shared host.
One more detail worth remembering: the model name in a request must include its namespace, written as ai/smollm2 rather than smollm2. Omit the ai/ prefix and the drop-down in Open WebUI stays empty.
Failure 3: localhost inside a container is not the host
This one is pure container networking and has nothing to do with DMR, but everyone hits it.
Inside a container, localhost means the container itself, not the host machine. So if Open WebUI's container is configured with http://localhost:12434, the request goes to port 12434 of the Open WebUI container, where nothing is listening.
The official verification command tests host reachability from inside a container:
docker run --rm alpine ping -c 1 host.docker.internal
If that command resolves and replies, name resolution is fine. If it does not, you are missing extra_hosts.
On Docker Engine for Linux there is a third address form. The docs list http://172.17.0.1:12434 for container access, but a Note on the same page warns that this interface may not be available by default within a Compose project. That is exactly the case where you fall back to extra_hosts. In practice I prefer the host-gateway form because it behaves identically on Docker Desktop and Docker Engine, which removes one whole class of environment-specific problem.
Failure 4: CORS blocks it and the frontend looks inert
The first three failures all leave a trace in the backend logs. This one does not. The backend is completely healthy, the browser console shows a CORS error, and the chat interface simply never sends anything.
The cause is that your frontend origin is not in DMR's allow list. The official Open WebUI integration docs give a direct fix: in Docker Desktop, open the Settings and go to the AI tab, find CORS Allows Origins, and add the origin your frontend runs on. The example the docs give is http://localhost:3131.
An origin is the complete combination of scheme, host, and port. Writing only localhost:3000 is not enough. It has to be http://localhost:3000, and leaving off the scheme still gets blocked. Open WebUI's own documentation makes the same point from its side: if Open WebUI runs in Docker while the model server is on the host, replace localhost in the URL with host.docker.internal.
Troubleshooting: the official checks for all four failures
Each of the four failures above has a verification step in the official docs that you can copy directly. Here they are reordered by what to test first:
# 1. Is DMR actually serving? Run on the host. JSON back means DMR is fine.
curl http://localhost:12434/api/tags
# 2. Were the models actually pulled?
docker model list
# 3. Can a container resolve the host? Should reply on Docker Desktop.
docker run --rm alpine ping -c 1 host.docker.internal
# 4. The OpenAI-compatible path must carry the /engines/v1 prefix.
curl http://localhost:12434/engines/v1/models
# 5. What a real inference request looks like. Content back means end to end works.
curl http://localhost:12434/api/chat \
-H "Content-Type: application/json" \
-d '{"model":"ai/smollm2","messages":[{"role":"user","content":"Hello!"}]}'
The gap between step 4 and step 5 demonstrates Failure 2 precisely. The same service exposes /engines/v1/models and /api/chat as two distinct path systems. Get the prefix wrong and you get a 404.
Condensed into a checklist, the four failures look like this:
- Error 1:
curl http://localhost:12434/api/tagsreturns nothing useful and the model drop-down is empty, with no error on the page. The cause isOLLAMA_BASE_URLfalling back to its 11434 default. The fix is to write the address explicitly into the environment block of your compose file. - Error 2: requests return 404 and the chat box reports a missing path. The cause is speaking the OpenAI-compatible protocol without the
/engines/v1prefix. The fix is to switch toOPENAI_API_BASE_URLand spell outhttp://host.docker.internal:12434/engines/v1. - Error 3: every request from inside the container fails and
host.docker.internalwill not resolve. The cause is a missingextra_hosts: "host.docker.internal:host-gateway"line. The fix is to add it, or to switch tonetwork_mode: host. - Error 4: the backend log looks clean but the browser never sends anything and the console shows one CORS error. The cause is a frontend origin that is not on the allow list. The fix is to add the full
http://host:portstring under Docker Desktop's Settings, AI, CORS Allows Origins.
Three limits the docs state outright
Beyond the connection problems, several documented limits affect your architecture choices directly:
- The Diffusers image-generation backend requires an NVIDIA CUDA GPU and runs only on Linux (x86_64 and ARM64). If you want image generation on Windows or macOS, this path is closed.
- The vLLM backend does not support CPU-only inference and requires NVIDIA CUDA. Native macOS and AMD GPUs are not supported, and on Windows it needs WSL2.
- A larger context is never free. The docs give a rough guide that each additional 1,000 tokens costs roughly 100 to 500 MB of memory, depending on model size. llama.cpp defaults to a 4096-token context, so step it down when you hit out-of-memory.
The docs also flag a performance note that saves a lot of confusion: the first request has to load the model into memory, so it is slow. Subsequent requests are much faster. If it stays slow, that points at a different problem, and you should either move to a smaller model or verify that GPU acceleration is actually engaging.
The smallest working combination
Compressing everything above into a single file you can hand to 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:
This is the complete example from the official docs. The model-setup service borrows the Docker socket to pull the models first, and Open WebUI waits for service_completed_successfully before starting, which saves you from juggling two terminals.
One last warning: WEBUI_AUTH=false is only appropriate for a single user on your own machine. For multi-user setups or anything exposed to a network, the docs require WEBUI_AUTH=true, and the first visit walks you through creating an admin account. Do not copy this file to a machine on the public internet.
Three dead ends I wasted time on
A few wrong turns worth naming, either mine or ones I watched other people take:
1. Suspecting an Open WebUI bug first. In almost every case its log states which address it is dialing, and the answer is in the configuration. Patching Open WebUI code is the last step, not the first.
2. Restarting Docker Desktop repeatedly. The DMR TCP switch lives under Settings and AI and has to be turned on explicitly. Restarting does not change that setting, it only wastes your time.
3. Assuming docker model run proves the whole path works. It tests DMR alone and never passes through Open WebUI. Only the network segment and CORS layer get exercised when you actually click send in a browser.
If you want the background on how the three inference engines differ and on the URL conventions beyond OLLAMA_BASE_URL, I wrote about that separately. If your problem is specifically "everything is installed and nothing connects," this post is ordered so you can match your symptom to a section.
👉 Join Xiaomi MiMo Platform: Leading AI model platform with cost-effective inference
👉 Join Aliyun AI: Top AI products with exclusive coupons for business innovation
📌 This article was AI-assisted generated and human-reviewed | TechPassive — An AI-driven content testing site focused on real tool reviews
🔗 Recommended Tools
These are carefully selected tools. Using our affiliate links supports us to keep producing quality content: