Linux rootless docker host.docker.internal IP

I need to access a socks proxy on my docker host on TCP port 1080.

With rootful docker, I can access this proxy inside the container at 172.17.0.1:1080, which is the default bridge network. With rootless docker, this does not work. I think it has something to do with network namespaces, but the reason isn’t of concern to me.

I’ve seen people say you can do --net=host or --add-host host.docker.internal:host-gateway, but neither of these things work in rootless docker. --net=host doesn’t seem to change anything. I can’t reach localhost:1080 or 172.17.0.1:1080 or 10.0.2.2:1080 or any other IP to get to port 1080 on the host. If I use the --add-host, it just maps the IP 172.17.0.1 to the name host.docker.internal, which again, doesn’t work.

In podman, there is a host.containers.internal, and in rootless podman, it maps to the actual IP of my host. So this works. If I set ALL_PROXY to the right IP address and port, this will work in rootless docker, but is it possible to get docker to do this mapping for me so I don’t need to know the IP?

Currently, I’m doing hacky things with --add-host host.containers.internal:$(curl -4 some_ip_finder_api), but it would be nice to…not do this. Any suggestions?

Thanks

So --add-host does work, you just need to set the right IP. Not a private internal one, but the “external” IP, the machine boots up with.

Um… Yes. That’s the problem. I don’t want to have to know the external IP of every docker host I’m on for this to work. And the curl thing is a hack. I’d like it to work like podman does, where host.containers.internal for rootless containers automatically maps to the host’s public IP, not the 172.17.0.1 or 10.0.2.2 IP where I cannot talk to the socks proxy port.

Which version of podman?

I tried Podman 3.4.4 which is the one I could install from the Ubuntu 22.04 APT repository. It seems it works about the same way as Docker, except it does not hjave an internal DNS server as Docker Desktop, but adds the host.containers.internal domain to the hosts file inside the container and the hostname points to the gateway of the ccontainer. It works only when you run the podman command as root. Otherwise podman uses the same network mode as rootless Docker called “slirp4netns”.

If you run

ps auxf

and search for slirp4netns in the output, you will find something like this when you run a container as a non-root user:

/usr/bin/slirp4netns --disable-host-loopback ...

Rootless Docker uses Rootlesskit which is from the same repo owner on GitHub as slirp4netns which is also used by rootlesskit.

This does not allow users to access the host using the container gateway regardless of what you use, Docker or Podman. So host.containers.internal works only as root. Maybe later versions do support it without root, I don’t know. If you share which version of Podman you are using, I can check it.

About the host network:

It looks like Podman supports accessing ports on the host when using host network, because then it just runs the container without additional security layer like rootlesskit. I’m not saying it is bad, it is just different. slirp4netns has the --disable-host-loopback flag I quoted before. I have read that it is supposed to disable accessing to loopback interfaces fo security reasons. You can change it in rootlesskit (instructions are at the beginning of dockerd-rootless.sh), but it was not enough for me as it is still indeed in a network namespace so I’m not sure why this flag is supported. Probably because there are other parameters as well like changing the network mode from slirp4netns to host or other possible values. I didn’t have time to try so I don’t know what it would do exactly, but it would be set for all containers and without root user, you have probably no right to manipulate host networks without network namespace, so it could mean you could run containers only on the host network witht your user.

Thw “hacky way” you used could easily be the best way in the end. Or you would need to set up a DNS server somewhere which resolves a hostname to your host IP.

I don’t see any problem with your solution even if an officially supported way would be better. Docker and compose can do many things, but not always enough and sometimes we need to write scripts and generate compose files or commands from a template.

I will save this topic as a bookmark and I will play with rootlesskit more. If I find out something, I will share. Until that, you can learn more about rootlesskit and keep your hacky way if you don’t find a better solution.

If you used rootless Docker only to run containers in a usernamespace, you can enable usernamespace in Rootful Docker as well and you could use the host-gateway keyword or implement host.docker.internal per container and per port as I described it here:

I’m beginning to think I’m not sure how podman does any of this.

On my Oracle Linux 8 system with podman 4.9.4-dev, there is an entry added to /etc/hosts for host.containers.internal and host.docker.internal pointing to the public IP of my host system.

On Debian 12 (WSL2) with podman 4.3.4, I have only host.containers.internal, and it points to 10.255.255.254. I have no idea what that is, so I assume it’s some kind of podman networking setup. The IP of my host is in the 172.16/12 range.

On my laptop with Fedora 41 and podman 5.1.0, I don’t have any entries in /etc/hosts and it doesn’t seem to know what hosts.containers.internal is.

So…I’m not sure what to make of this, but I guess I’ll use my curl hack for the time being.

Thanks.

That shouldn’t be true either… At least not in Docker Desktop which supports that domain. host.docker.internal is to access a port on the loopback interface of your host. Internally it points (should point) to an IP that works as a proxy and forwards the request to the host’s loopback interface. Unless it is changed or it is different in some cases I don’t know about.

Than you for the version numbers. I will see if I have time to test podman again.