Container cannot reach host services — localhost vs host.docker.internal
curl localhost inside container returns connection refused
Focused incident mode — strips away everything but this runbook.
Symptoms
- curl localhost inside container returns connection refused
- Application inside container cannot reach a database on the host
- Connection to host port works from outside Docker but not from within
localhost inside a bridge-mode container is the container's own loopback. Always use the gateway IP or host.docker.internal alias to reach the host.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Container network mode
docker inspect <CONTAINER> --format='{{.HostConfig.NetworkMode}}'Host IP from container
docker exec <CONTAINER> ip route show default
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- Container uses bridge network (default)
- curl localhost inside container connects to 127.0.0.1 (loopback inside container)
- Host service listens on 0.0.0.0 but is on the host network
Confirm before fixing
docker exec <CONTAINER> ping -c1 127.0.0.1 && docker exec <CONTAINER> ping -c1 172.17.0.1Compare localhost vs gateway reachability
Fix
docker run --add-host=host.docker.internal:host-gateway <IMAGE>Use host.docker.internal to reach the host
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
docker inspect <CONTAINER> --format='NetworkMode: {{.HostConfig.NetworkMode}}'Check network mode
docker inspect <CONTAINER> --format='{{(index .NetworkSettings.Networks "bridge").Gateway}}'Find the host gateway IP
docker exec <CONTAINER> sh -c 'wget -qO- http://172.17.0.1:<HOST_PORT>/ || echo FAIL'Test host reachability via gateway
docker run --add-host=host.docker.internal:host-gateway <IMAGE>Use host.docker.internal alias to reach the host
Prevention
- Document that containers must never assume localhost refers to the host.
- Use --add-host=host.docker.internal:host-gateway for all host-dependent containers.
- Bind host services to 0.0.0.0 when containers need access (and use firewall rules for security).
- Prefer explicit service-to-service discovery over host-dependency.
Related runbooks
Same stack, same failure family — worth a skim.
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.