对于Linux,不能更改localhost服务绑定到的接口
我们需要解决两个问题
获取主机的IP使我们的本地主机服务可用于Docker
第一个问题可以使用qoomon的docker主机映像来解决,正如其他答案所给出的那样。
您需要将此容器添加到与其他容器相同的网桥网络中,以便可以访问它。打开容器中的一个终端,确保可以ping dockerhost。
bash-5.0# ping dockerhost
PING dockerhost (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.523 ms
现在,更难的问题是,让docker可以访问该服务。
我们可以使用telnet检查是否可以访问主机上的端口(您可能需要安装此端口)。
问题是,我们的容器只能访问绑定到所有接口的服务,例如SSH:
bash-5.0# telnet dockerhost 22
SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3
但仅绑定到localhost的服务将无法访问:
bash-5.0# telnet dockerhost 1025
telnet: can't connect to remote host (172.20.0.2): Connection refused
这里的正确解决方案是将服务绑定到dockers网桥网络。然而,这个答案假设你不可能改变这一点。因此,我们将改用iptables。
首先,我们需要找到docker在ifconfig中使用的网桥网络的名称。如果您使用的是未命名的桥,则这将只是docker0。然而,如果你使用的是一个命名网络,你将有一个以br开头的网桥,docker将使用它。我的是br-5cd80298d6f4。
一旦我们有了这个桥的名称,我们就需要允许从这个桥到本地主机的路由。出于安全原因,默认情况下禁用此功能:
sysctl -w net.ipv4.conf.<bridge_name>.route_localnet=1
现在设置iptables规则。由于我们的容器只能访问docker网桥网络上的端口,所以我们将假装我们的服务实际上绑定到这个网络上的一个端口。
为此,我们将所有请求转发到<docker_bridge>:port到localhost:port
iptables -t nat -A PREROUTING -p tcp -i <docker_bridge_name> --dport <service_port> -j DNAT --to-destination 127.0.0.1:<service_port>
例如,对于端口1025上的服务
iptables -t nat -A PREROUTING -p tcp -i br-5cd80298d6f4 --dport 1025 -j DNAT --to-destination 127.0.0.1:1025
您现在应该可以从容器访问服务:
bash-5.0# telnet dockerhost 1025
220 127.0.0.1 ESMTP Service Ready