3

I have two containers running on a docker bridge network (this can be the default docker0, or a user-defined bridge). If I publish ports from one container, the other container cannot access those published ports via the host IP address.

Example:

$ docker run --detach -p 80:80 nginx
$ docker run --rm -it centos \
  /bin/bash -c "yum install -y wget && wget http://${HOST_IP}"
...
Connecting to ${HOST_IP}:80... failed: No route to host.

In the above example, the nginx server can be accessed from the host and other servers on the network (or internet). However, the centos docker container, which has full network access, is unable to connect to port 80 on the host. All ports on the host can be accessed without issue, as long as it is not on a docker network bridge.

I have found completely disabling firewalls (firewalld and iptables) and restarting the docker service allows access, so I am reasonably certain this is a firewall issue. I found this docker libnetwork PR, but it hasn't seen any activity in 6 months.

Am I missing something fundamental about docker here? Shouldn't two containers on the same bridge network be able to communicate over a publish port? I should add that if I try to access the nginx port directly using the internal private network IP (172.X.X.X) from inside the centos container then it works. It is only when connecting out to the published host port.

I have found the above happens with both the latest centos (7.4.1708) and fedora (28) images.

plasmid87
  • 1,888
  • 15
  • 17
  • 1
    Possible duplicate of [Loopback to forwarded Public IP address from local network - Hairpin NAT](https://serverfault.com/questions/55611/loopback-to-forwarded-public-ip-address-from-local-network-hairpin-nat). It might not be obvious at first glance that this is what's going on, but if all the containers are on a virtual bridge from which the host does NAT to the outside world, that is in fact an identical setup. The problem isn't docker-specific. – MadHatter May 07 '18 at 06:04
  • I'm conflicted with this question. I have a solution to my problem, which was to disable `userland-proxy` as [described here](https://stackoverflow.com/questions/44413816/how-to-disable-userland-proxy-for-docker-compose), but it doesn't answer my original question - why can't containers access published ports from the host IP by default? I agree that hairpin NAT is probably the desired behavior, but among the enormous number of firewall rules generated by docker, isn't there one to do this already? Shouldn't docker create the firewall rules properly automatically? – plasmid87 May 07 '18 at 20:06
  • That would be a question for the docker developers, not something we can answer here. Sorry. – MadHatter May 08 '18 at 06:33
  • I'm going to close this question. As a final note, if I re-enable `userland-proxy` and open port 80 with firewalld / iptables (e.g., `$ firewall-cmd --add-service=http --permanent; firewall-cmd --reload`) then I can get access from other containers and the public port! There is an [ongoing thread about this issue here](https://github.com/moby/moby/issues/32138). – plasmid87 Jul 22 '18 at 23:13
  • I'm voting to close this question as off-topic because this is a Docker-internals problem, which I will need to take up with the developers directly – plasmid87 Jul 22 '18 at 23:16

0 Answers0