Coding Agents & Terminal · recorded 2026-08-29 · applies to 1 tool(s) ✓ Verified

Problem: Docker container cannot reach a service on the host (localhost inside the container is the container itself, not the host) —— Trove problem library

Verified 2026-08-29can't reach host services from a container — localhost is the container itself; run with --add-host host.docker.internal:host-gateway and use host.docker.internal inside.

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.

AddressLinux defaultNotes
localhost inside containerPoints to the container itselfCan't reach host services
172.17.0.1 (docker0 gateway)✅Default gateway = the host
host.docker.internal❌ absent by defaultNeeds --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

EnvironmentNotes
Native Linuxhost.docker.internal absent by default; needs --add-host (measured: bad address)
Docker Desktop (Win/mac)host.docker.internal built in
Host service listeningMust bind 0.0.0.0, not only 127.0.0.1

| Compose | `extra_hosts:

  • "host.docker.internal:host-gateway"` |
--network hostLinux 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):

  1. 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 with ip -4 addr show docker0). Note the host service must listen on 0.0.0.0, not only 127.0.0.1, otherwise it stays unreachable from other IPs.
  2. 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"). Afterwards host.docker.internal` behaves like Docker Desktop. macOS/Windows Docker Desktop already has it without config.
  1. --network host (simplest, Linux only): docker run --network host shares the host network namespace; localhost inside the container IS the host, so http://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-gateway same 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:

Applicable tools (1)

This problem is linked from the tool pages below — reachable from either side.

docker

Bundled solutions (combos)

This problem is part of the following verified bundles.

Source & evidence

Recorded Verified ✓ VerifiedApplies to 1 tool(s)
Entries contain locally measured or reviewable-source solutions; unmeasured items are explicitly labeled.

Source: https://github.com/hankliu62/interview/issues/2102

← Coding Agents & Terminal domain | Problem Catalog Experience | Facing another issue? Go to the Helpdesk