Connection refused on host.docker.internal

I want to connect to a service running on the host from a container.

This is described in the docs here,

I start a webserver on the host listening on port 8000, then I do this,

$ docker run --rm -it alpine sh
# apk add curl
# curl http://host.docker.internal:8000

It just doesn’t work. I’ve been trying to figure this out for days. Any help would be much appreciated.

Are there some firewall rules that might be in place or something? I saw somewhere else that this might not even be possible on macOS?

How do I get this to work?

Docker Desktop For Mac 4.21.1 (114176)
macOS Ventura 13.3.1
Apple M2

That special hostname has to be in your host file to work. From containers it is handled by Docker Desktop’s internal dns server. I checked my hosts file on my Mac and found this:

File:/etc/hosts

# Added by Docker Desktop
# To allow the same kube context to work on the host and the container:
127.0.0.1 kubernetes.docker.internal
# End of section

and not host.docker.internal. I’m not sure why it is missing in my case, but you can add it manually

127.0.0.1 host.docker.internal

Thanks.

I added the line 127.0.0.1 host.docker.internal to /etc/hosts and restarted the computer.

Still doesn’t work.

I’ve got no idea how to fix this. There is nothing on the internet about this problem. How do I trouble shoot something like this?

1 Like

I think I misunderstood the commands in your first post. I thought you wanted to access a service from the host using host.docker.internal, but you actually tried to acccess it from the container. Adding the domain to the hosts file on your host will not change anything in the container.

Now I tried what you did and works perfectly. how did you started the service on the host? Does that service listens on 127.0.0.1 or LAN IP? I always forget it but host.docker.internal is not just dns record to point to the IP of your host. It will point to 127.0.0.1 of your host which is not possible otherwise unless manually setting up a proxy server on the host.

The documentation says:

We recommend that you connect to the special DNS name host.docker.internal which resolves to the internal IP address used by the host.

That’s true, but the host is actually the virtual machine not your physical host. Then the request is forwarded to your physical hosts loopback ip address.

When I first forwarded the port from my host’s LAN IP, I had to accept it. I tried it to test what happens when nothing listens on 127.0.0.1. I got “Couldn't connect to server

Have you tried using curl on your Mac now that you added the domain to the hosts file?

Good evening.

What do you see in the hosts file?

There’s something that looks like?

192.168.192.1 host.docker.internal

If not, you need to put that entry in there. But the problem is that every time you start the container it gets a random ip.

To overcome this, you need to use a script that will determine which ip is assigned to the container and write it to the hosts file.

entrypoint.sh

#!/bin/sh
set -e

HOST_DOMAIN="host.docker.internal"
if ! ping -q -c1 $HOST_DOMAIN > /dev/null 2>&1
then
 HOST_IP=$(ip route | awk 'NR==1 {print $3}')
 # shellcheck disable=SC2039
  echo -e "$HOST_IP\t$HOST_DOMAIN" >> /etc/hosts
fi

# first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
set -- php-fpm "$@"
fi
exec "$@"

Then use the Dockerfile to copy it into the container

FROM ****

 ************

 COPY ./path_to_file/entrypoint.sh /usr/local/bin/docker-php-entrypoint
 RUN chmod +x /usr/local/bin/docker-php-entrypoint

You will then be able to access it from the container

 docker compose run --rm container_name curl -I host.docker.internal:8000

HTTP/1.1 200 OK
Server: nginx
Date: Fri, 08 Sep 2023 18:38:56 GMT
Content-Type: text/html
Content-Length: 1310
Connection: keep-alive
Accept-Ranges: bytes
Last-Modified: Fri, 08 Sep 2023 18:38:56 GMT
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Xss-Protection: 1; mode=block

Have a similar problem, but I want to connect to a container running locally from one app to another app. This host.docker.internal is not working only in my mac strangely.

That is a Docker Desktop feature. See this post: