简而言之,一切正常,直到我尝试从docker容器中访问我的apache服务器互联网。传入的数据包到达 docker 容器,但传出的数据包被 docker-machine 上的 NAT 接口丢弃。
我的设置是
- 典型的家庭局域网设置,带有连接到互联网的路由器
- 运行 docker 的 osx 机器(即 docker-machine 又名 boot2docker)
- 运行 apache 的 docker 容器(将端口 80 公开为 11111)
- 我也在 osx(我的主机)上运行 apache,它将作为故障排除工具。
- 我为 docker-machine 添加了一个桥接接口,将 docker-machine 直接连接到我的 LAN,并从我的路由器获取 IP。
- 在我的路由器(192.168.1.1)上,我已将 11111 端口转发到我的 docker-machine IP(192.168.1.102)
我可以做什么
- 由于
docker-machine 上的桥接接口,我可以从我的主机和 LAN 上的另一台计算机(全部 192.168.1.X)连接到 apache。192.168.1.102:11111 和使用
http://:11111 - 所以显然我的域名正确解析了它的 IP,并且我的路由器上的端口转发工作正常。
- 我还可以轻松地从互联网访问我的主机(osx)上的 Web 服务器
我尝试过
- 使用 pfctl 在我的主机(osx)上进行端口转发
- 在我的容器上使用 --net=host
我已经缩小了问题的范围(使用 tcpdump 和其他实验),当我从 LAN 上的计算机连接到容器中的 Web 服务器时,数据包会流经 docker-machine 中的桥接接口 (192.168.1.102)。当我从互联网连接时,传入数据包会流经 192.168.1.102,但返回数据包不会。相反,它会通过 docker-machine 上的 NAT 接口并被丢弃。我已经通过在 docker-machine 内部对 NAT 接口执行“ifconfig eth0 down”来证明这一点。现在显然这会搞砸我的 docker-machine,因为我无法再运行 docker 命令,并且它会终止我当前的 ssh 会话。但是当我这样做时,从互联网到容器中的 Web 服务器的连接就可以正常工作了!所以我证明返回数据包是问题所在。
现在,我可以使用 docker-machine 中的 iptables 正确路由数据包,以便它从桥接接口而不是 NAT 接口出去吗?我试过了,但没有成功。这是我在 docker-machine 上的 iptables 规则。我想路由来自我的容器的所有数据包,源端口为 11111,并将它们路由到 eth1(桥接接口)。
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
我的做法是不是全错了?有没有我还没探索过的标准设置方法?