TinkerLab
04 // DIAGNOSISDocker / ComposeApple Silicon MacNVIDIA GPUn8n Automation~8 min read & lab

Container Cannot Connect to Host Model: Minimal Reproduction & Diagnostic Steps

Solve the #1 self-hosted AI failure (`ECONNREFUSED` / `ETIMEDOUT` calling port 11434 from Open WebUI, n8n, or Dify) in three deterministic verification commands.

[KEY VERIFIED TAKEAWAY / TL;DR]In Tinker AI Lab's reproducible verification of "Container Cannot Connect to Host Model: Minimal Reproduction & Diagnostic Steps" (tested on Verified on Ubuntu 24.04 (Docker Engine 27.x + UFW) & macOS 15 (Docker Desktop 4.36) with Docker Engine 27.x, Ollama 0.5.7, Open WebUI v0.5.10, n8n 1.76.x, verified 2026-10-23): Solve the #1 self-hosted AI failure (`ECONNREFUSED` / `ETIMEDOUT` calling port 11434 from Open WebUI, n8n, or Dify) in three deterministic verification commands. Offline capability is classified as "Local Loopback & Bridge Network Only" (Includes firewall rules to keep port 11434 isolated from external LAN/WAN while opening it to local containers.), with key operational boundary: Using `network_mode: host` fixes Linux networking instantly, but is NOT supported on Docker Desktop for macOS or Windows.
REPRODUCIBILITY MANIFEST // TESTED SPECS & LIMITS
Last Verified: 2026-10-23
Tested Hardware & OS

Verified on Ubuntu 24.04 (Docker Engine 27.x + UFW) & macOS 15 (Docker Desktop 4.36)

Pinned Stack & Model Versions
Docker Engine 27.xOllama 0.5.7Open WebUI v0.5.10n8n 1.76.x
Offline & Network Boundary
Local Loopback & Bridge Network Only

Includes firewall rules to keep port 11434 isolated from external LAN/WAN while opening it to local containers.

Known Limits & Failure Modes
  • Using `network_mode: host` fixes Linux networking instantly, but is NOT supported on Docker Desktop for macOS or Windows.
  • Binding `OLLAMA_HOST=0.0.0.0` on a cloud VPS without a firewall immediately exposes your model server to internet scanners.
Hit an edge-case failure?Open Troubleshooter →

1. Minimal Reproduction of the Three Distinct Failure Modes

Not all connection failures are the same. Run a one-line alpine probe container to see which exact error code you hit: • **`Connection refused` (Instant)**: Either you wrote `localhost:11434` inside the container, OR host Ollama is bound only to `127.0.0.1:11434`. • **`bad address 'host.docker.internal'` (Instant)**: You are on Linux Docker Engine and forgot `extra_hosts: ["host.docker.internal:host-gateway"]`. • **`Operation timed out` (Hangs 5–30s)**: Host Ollama is listening on `0.0.0.0`, DNS resolves to `172.17.0.1`, but Linux `ufw` or `firewalld` is silently dropping packets from the `docker0` interface.
Table 1: Container-to-Host Port 11434 Symptom, Layer & Fix Matrix
Terminal Error OutputFailing LayerAffected OSDeterministic Fix
Connection refused (127.0.0.1:11434)Container NamespaceAll (Mac / Linux / Win)Use http://host.docker.internal:11434
Connection refused (172.17.0.1:11434)Host Socket BindmacOS & Linux systemdSet OLLAMA_HOST=0.0.0.0:11434 on host
wget: bad address 'host.docker.internal'Container /etc/hostsNative Linux Docker EngineAdd extra_hosts: ["host.docker.internal:host-gateway"]
wget: download timed out (after 5s)Host Firewall (UFW/iptables)Ubuntu / Debian with UFWufw allow from 172.16.0.0/12 to any port 11434
One-Line Minimal Reproduction Probe
docker run --rm --add-host=host.docker.internal:host-gateway alpine:3.20 \
  sh -c "getent hosts host.docker.internal && wget -qO- --timeout=5 http://host.docker.internal:11434/api/version"

2. Security Boundary: Opening to Containers Without Exposing to the Internet

When you set `OLLAMA_HOST=0.0.0.0:11434` on Linux so Docker bridge containers (`172.17.0.0/16` or custom Compose networks in `172.18.0.0/16`) can reach the host, port 11434 also binds to your public/LAN ethernet adapter. Always restrict inbound access to private RFC1918 bridge subnets (`172.16.0.0/12`) via `ufw` or bind directly to the `docker0` interface IP (`172.17.0.1:11434`).

3. Multi-Container Compose Bridge vs Host Native Performance

On Linux with NVIDIA GPUs, you can alternatively run BOTH Ollama and Open WebUI/n8n inside the same `docker-compose.yml` network and address Ollama via `http://ollama:11434` without touching host ports or UFW rules. On Apple Silicon Macs, however, Ollama **must** run natively on macOS host to access Metal GPU acceleration, making `http://host.docker.internal:11434` mandatory.
FIELD Q&A // 常见实测疑问与边界解答

Frequently Asked Questions & Edge Cases

Q: Why does `ufw allow from 172.17.0.0/16` still fail when I use `docker compose up`?

`172.17.0.0/16` only covers the default `docker0` bridge. Docker Compose automatically creates a new user-defined bridge network for each project using subnets like `172.18.0.0/16`, `172.19.0.0/16`, etc. Allowing the full private block `172.16.0.0/12` covers all Compose project bridges safely.

Q: After setting `launchctl setenv OLLAMA_HOST "0.0.0.0:11434"` on macOS, why is it still listening on `127.0.0.1`?

macOS GUI apps only read `launchctl` environment variables when launched. You must click the Ollama icon in the top menu bar -> **Quit Ollama**, and reopen it from `/Applications/Ollama.app` for the new socket bind to take effect.

REPRODUCIBLE ARTIFACT // 配套可参数化附件

Container-to-Host Local LLM Connectivity Diagnostic Script

Tests host bind address (127.0.0.1 vs 0.0.0.0), host.docker.internal DNS resolution, and bridge firewall rules.

diagnose-container-llm.sh ↗
Edit variables above to update the configuration live
#!/usr/bin/env bash
# Tinker AI Troubleshooting — Container <-> Host Local Model Diagnostic (Guide #6)
set -euo pipefail

PORT="11434"
CONTAINER="tinker-open-webui"

echo "=== Step 1: Check Host Listening Address on Port $PORT ==="
if lsof -nP -iTCP:"$PORT" -sTCP:LISTEN 2>/dev/null | grep -q "127.0.0.1:$PORT"; then
  echo "[FAIL] Host service is bound ONLY to 127.0.0.1:$PORT."
  echo "  -> Fix: Set OLLAMA_HOST=0.0.0.0:$PORT on the host service and restart."
else
  echo "[OK] Host service is not restricted to loopback only."
fi

echo "=== Step 2: Probe host.docker.internal from inside $CONTAINER ==="
docker exec "$CONTAINER" sh -c "getent hosts host.docker.internal && wget -qO- --timeout=5 http://host.docker.internal:$PORT/api/version" \
  && echo "[OK] Container reached host model API successfully!" \
  || echo "[FAIL] Container cannot reach host.docker.internal:$PORT. Ensure extra_hosts: ['host.docker.internal:host-gateway'] is set."

More Reproducible Engineering Guides

View All 42 Guides →