Fixing host.docker.internal on Linux
If you've ever moved a Docker project from a Mac to a Linux server, you've probably hit this error:
Connection refused: host.docker.internal:3000
On macOS and Windows, host.docker.internal is a magic DNS name that resolves to your host machine's IP address. It's incredibly useful for connecting containers to local databases or APIs running outside of Docker.
But on Linux? It doesn't exist by default.
Why?
On macOS and Windows, Docker runs inside a lightweight virtual machine. host.docker.internal is a helper to bridge the gap between that VM and your actual host OS.
On Linux, Docker runs natively. There is no VM. The "host" is just... the host. But because containers are isolated, they still don't know the host's IP address automatically.
The Fix
You don't need hacky scripts or hardcoded IPs. Docker 20.10+ supports a special host-gateway value.
In Docker Compose
Add extra_hosts to your service definition:
services:
my-app:
image: my-app:latest
extra_hosts:
- "host.docker.internal:host-gateway"
That's it. Now host.docker.internal will resolve to the host's Docker gateway IP (usually 172.17.0.1), allowing your container to talk to services listening on the host.
Important: make sure the service on the host is listening on
0.0.0.0(or on the Docker bridge IP), not just127.0.0.1. Otherwise the container can reach the host, but the host refuses the connection.
In Docker CLI
docker run --add-host host.docker.internal:host-gateway my-image
A Note on Firewalls
If it still doesn't work, check your firewall (UFW or iptables). UFW may block forwarded traffic from Docker networks.
To allow traffic from the default Docker subnet:
sudo ufw allow from 172.17.0.0/16
This permits container → host connections without exposing the docker0 interface itself.
Tired of Networking Issues?
Networking is the hardest part of self-hosting.
At Hostim.dev, we handle the networking layer for you. Deploy your containers and let them talk to each other securely, without messing with extra_hosts or firewalls.