1

In short, everything works until I try to access my apache server in a docker container from the internet. The incoming packets reach the docker container, but the outgoing packets get dropped by the NAT interface on docker-machine.

My setup is

  • typical home LAN setup with a router connected to the internet
  • osx machine running docker (ie - docker-machine aka boot2docker)
  • a docker container running apache (exposing port 80 as 11111)
  • I have apache running on osx (my host machine) as well which will serve as a troubleshooting tool.
  • I added a bridged interface to docker-machine which connects docker-machine directly to my LAN and it gets a IP from my router.
  • on my router (192.168.1.1) I've port forwarded 11111 to my docker-machine IP (192.168.1.102)

what I can do

  • I can connect to apache from my host and from another computer on my LAN (all 192.168.1.X) because of the bridge interface on
    docker-machine. both 192.168.1.102:11111 and using
    http://:11111
  • so obviously my domain resolves it's IP properly and port forwarding on my router works fine.
  • I can also easily access the web server on my host machine (osx) from the internet

what I've tried

  • port forwarding on my host (osx) using pfctl
  • using --net=host on my container

I've narrowed down the problem (using tcpdump and other experimentation) that when I connect to the web server in the container from a computer on my LAN the packets flow through the bridged interface (192.168.1.102) in docker-machine. When I connect from the internet the incoming packet flows through 192.168.1.102, but the return packet does not. Instead it goes through the NAT interface on docker-machine and gets dropped. I've proved this by doing "ifconfig eth0 down" on the NAT interface from inside docker-machine. Now obviously this screws up my docker-machine because I can no longer run docker commands and it kills my current ssh session. But when I did this, connectivity to the web server in the container from the internet works! So I proved that the return packet is the problem.

Now, can I use iptables inside docker-machine to route the packet properly so that it goes out the bridged interface instead of the NAT interface? I've tried it without success. Here is my iptables rules on docker-machine. I want to route any packets coming from my container with a source port of 11111 and route them to eth1 (the bridged interface).

sudo iptables -I FORWARD 1 -i docker0 -o eth1 -p tcp --syn --sport 11111 -m conntrack --ctstate NEW -j ACCEPT

docker@default:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp spt:11111 flags:FIN,SYN,RST,ACK/SYN ctstate NEW
DOCKER-ISOLATION  all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (1 references)
target     prot opt source               destination

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

enter image description here

Am I going about this all wrong? Is there a standard way to set this up that I haven't explored?

  • Can you dump your rules with this command instead: iptables-save . It's really more clear for me. And I'm asking because I don't see any nat rule, and for sure there are some – A.B Nov 21 '16 at 22:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.