Quick fix
# One-liner: --add-host maps host.docker.internal to the host (recommended, config-file friendly)
docker run --add-host host.docker.internal:host-gateway <image>
Inside the container, host.docker.internal now reaches host services.
What you will run into
A service runs on the host (MySQL, Redis, a local API...), and the container tries to reach it with localhost or 127.0.0.1, getting Connection refused.
The service is fine on the host itself (host curl 127.0.0.1:port works); switching to host.docker.internal on Linux also fails (bad address).
Why this happens
Containers have their own network namespace: localhost/127.0.0.1 inside a container refers to the container itself, not the host.
On the default bridge network, the host service simply doesn't exist inside the container, so you get Connection refused (not a firewall issue — the address points at the container itself).
host.docker.internal is auto-injected only by Docker Desktop (Windows/macOS); native Linux Docker doesn't have it by default.
| Address | Linux default | Notes |
|---|---|---|
| localhost inside container | Points to the container itself | Can't reach host services |
| 172.17.0.1 (docker0 gateway) | ✅ | Default gateway = the host |
| host.docker.internal | ❌ absent by default | Needs --add-host injection |
Each container has its own network namespace: localhost/127.0.0.1 inside the container resolves to the container's own loopback interface, and the host's services are simply not in that address space — Connection refused is not a firewall block, it means "nothing is listening on that address".
The default gateway of the bridge network (docker0, usually 172.17.0.1) is the host's entry point; host.docker.internal is just a DNS alias injected by Docker Desktop — native Linux Docker has no such entry, so resolution fails.
Deterministic takeaway: to reach the host from a container, use the gateway IP (172.17.0.1, universal on Linux) or inject the alias with --add-host host.docker.internal:host-gateway (config-file friendly);
and the host service must listen on 0.0.0.0 — a service bound only to 127.0.0.1 is unreachable from any external IP.
Both addressing and listening must be right.
Step by step
1. Host IP (most universal) — Required
The default gateway of the bridge network is the host:
ip -4 addr show docker0
Access http://172.17.0.1:<port> from inside the container. Note the host service must listen on 0.0.0.0, not only 127.0.0.1, or it stays unreachable from other IPs.
2. host.docker.internal (recommended) — Required
docker run --add-host host.docker.internal:host-gateway <image>
In compose use `extra_hosts:
- "host.docker.internal:host-gateway"`. Docker Desktop on macOS/Windows already provides it without config.
3. --network host (simplest, Linux only) — Required
docker run --network host <image>
Shares the host network namespace — localhost inside the container is the host. Cost: no port isolation; container and host share the port space.
How to confirm it works
Reaching the host service from inside the container succeeds (measured output shape):
Method 1: wget http://172.17.0.1:8123/ → success (exit 0)
Method 2b: host.docker.internal:8123 after --add-host → success (exit 0)
Method 3: localhost:8123 with --network host → success (exit 0)
Reproduction baseline: default-network container wget http://localhost:8123/ → Connection refused (exit 1, measured).
Other environments
| Environment | Notes |
|---|---|
| Native Linux | host.docker.internal absent by default; needs --add-host (measured: bad address) |
| Docker Desktop (Win/mac) | host.docker.internal built in |
| Host service listening | Must bind 0.0.0.0, not only 127.0.0.1 |
| Compose | `extra_hosts:
- "host.docker.internal:host-gateway"` |
| --network host | Linux only, no port isolation |
|---|
Symptom
A service runs on the host (MySQL, Redis, a local API...), but the container cannot connect via localhost or 127.0.0.1:
wget: can't connect to remote host: Connection refused
# or mysql: connect to 127.0.0.1 ... failed (Can't connect)
# or curl: (7) Failed to connect to localhost port 8123: Connection refused
Key traits: the service works fine on the host itself (curl 127.0.0.1:port works); the container uses the default bridge network; host.docker.internal also fails on Linux with a bad address resolution error.
Cause
Containers have their own network namespace: localhost/127.0.0.1 inside a container refers to the container itself, not the host. On the default bridge network, the service on the host simply doesn't exist inside the container, hence Connection refused (not a firewall issue — the address points at the container itself). host.docker.internal is auto-injected only by Docker Desktop (Windows/macOS); native Linux Docker does not have it, so it fails DNS resolution.
Solution
Three ways (all verified on Linux; pick by scenario):
- Host IP (most universal): the default gateway of the bridge network is the host. Inside the container use
http://172.17.0.1:<port>(the docker0 IP; find it withip -4 addr show docker0). Note the host service must listen on0.0.0.0, not only127.0.0.1, otherwise it stays unreachable from other IPs. - host.docker.internal (recommended for config files): on Linux add
--add-host host.docker.internal:host-gateway(in compose: `extra_hosts:
- "host.docker.internal:host-gateway"
). Afterwardshost.docker.internal` behaves like Docker Desktop. macOS/Windows Docker Desktop already has it without config.
- --network host (simplest, Linux only):
docker run --network hostshares the host network namespace; localhost inside the container IS the host, sohttp://localhost:<port>just works. Trade-off: no port isolation — the container shares the host's port space.
Verification Evidence
- Local repro (2026-08-29, WSL Ubuntu, docker 29.1.3, alpine:3.20; host python3 http.server :8123 listening on 0.0.0.0):
- Repro:
wget http://localhost:8123/inside container →Connection refused(exit 1); - Method 1:
wget http://172.17.0.1:8123/(docker0 host-side IP) → success (exit 0); - Method 2a:
wget http://host.docker.internal:8123/→bad address 'host.docker.internal:8123'(no such hostname on Linux by default, exit 1); - Method 2b: with
--add-host host.docker.internal:host-gatewaysame URL → success (exit 0); - Method 3: with
--network host,wget http://localhost:8123/→ success (exit 0).
Evidence details kept locally (2026-08-29)
Related canonicals
Read in order: precondition -> same root / same domain / related:
- Precondition (rule out first):
- Cannot connect to the Docker daemon (precondition: container starts = daemon OK)
Applicable tools (1)
This problem is linked from the tool pages below — reachable from either side.
dockerBundled solutions (combos)
This problem is part of the following verified bundles.
Source & evidence
← Coding Agents & Terminal domain | Problem Catalog Experience | Facing another issue? Go to the Helpdesk