如何将Docker容器通过独立IP暴露给局域网

菜鸟查了很多资料才找到解决办法,Hats off to the shares!

https://blog.csdn.net/lvshaorong/article/details/69950694

问题需求:

先说我的需求:

简单说:Centos上启动了几个容器,我要通过与Centos在同一局域网下的Win 10 PC去访问这些docker,但是Win 10 和 容器没有在一个网段下,不能直接通信。

具体点:我把Centos作宿主机,利用Docker启动一个hadoop集群,我要通过与Centos在一个局域网下的Win10 PC机通过Java API的方式与集群中的节点进行通信。其实这个需求是我在实验中遇到问题后一步步定位到的,更具体地问题解决过程可以看我的另一篇文章。

我们知道,在Docker启动时会产生虚拟网卡,可以把这个网卡理解为一个虚拟交换机,然后每个容器都连接在这个交换机下,每个容器都拥有自己单独的网卡和IP。现在整理下我们的需求中大致的网络拓扑:

Centos宿主机(假设IP为192.168.1.237)和Win 10 (假设IP为192.168.1.135)在同一局域网下,Centos上运行多个docker(假设所处网段为172.19.0.1/16)。这样的拓扑结构下,Centos宿主机可以和其上运行的容器通信,Centos宿主机可以和Win 10通信。

通过查找各种资料,看到一些解决方案,比如,让容器使用静态独立外部IP等,由于我只是在学习hadoop的时候把Docker作为一个使用工具,不想花费太多时间在Docker上,所以希望尽可能简单的解决问题,最终决定了使用文章开头提到的参考资料。这个方案下的解决思路:

解决方案思路:

Centos宿主机查看网卡和IP:

[root@centos7 ~]# ifconfig
br-af4e4c5cd5b4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.19.0.1  netmask 255.255.0.0  broadcast 172.19.255.255
        inet6 fe80::42:6cff:fe9b:7ed2  prefixlen 64  scopeid 0x20<link>
        ether 02:42:6c:9b:7e:d2  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 656 (656.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:f7ff:feb9:485d  prefixlen 64  scopeid 0x20<link>
        ether 02:42:f7:b9:48:5d  txqueuelen 0  (Ethernet)
        RX packets 165569  bytes 5882890 (5.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 24244  bytes 81774073 (77.9 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.237  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::1823:15e9:2383:bb13  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:fd:d2:c8  txqueuelen 1000  (Ethernet)
        RX packets 5306454  bytes 1201239143 (1.1 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 354841  bytes 298525072 (284.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 135  bytes 9108 (8.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 135  bytes 9108 (8.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth0b92e02: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::d02a:1bff:fe77:4d9a  prefixlen 64  scopeid 0x20<link>
        ether d2:2a:1b:77:4d:9a  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 656 (656.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

这里面br-af4e4c5cd5b4和docker0都是Docker创建的虚拟网卡,其中docker0是Docker启动时自己创建的,br-af4e4c5cd5b4是我为我的集群自定义的网络,都是桥接模式,这里我以br-af4e4c5cd5b4介绍,在看文章的你可能直接使用的docker0,也可能也是制定了自定义的网络,但是都没差别的,类比过去就好 ,主要注意IP就成。ens160这块网卡就是与Win 10在同一局域网下。

通过在Centos宿主机查看路由信息可以看出:因为有了这两块网卡,Centos知道到目标地址为172.19.0.0/16以及到192.168.1.0/24的路由。从下面的结果可以看出,172.19.0.0/16网段的数据包通过br-af4e4c5cd5b4发出,192.168.1.0/24数据包通过ens160发出。

[root@centos7 ~]# ip route
default via 192.168.1.1 dev ens160 proto dhcp metric 100 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
172.19.0.0/16 dev br-af4e4c5cd5b4 proto kernel scope link src 172.19.0.1 
192.168.1.0/24 dev ens160 proto kernel scope link src 192.168.1.237 metric 100 

因为有了br-af4e4c5cd5b4,所以Centos可以和dockers通信,Centos在于dockers通信时使用的IP是172.19.0.1;因为有了ens160,所以Centos可以和Win 10通信,Centos于Win 10通信时使用的IP是192.168.1.237。

在容器里面,查看下容器的网卡和IP,这个容器的IP为172.19.0.2

[root@hadoop-0 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.19.0.2  netmask 255.255.0.0  broadcast 172.19.255.255
        ether 02:42:ac:13:00:02  txqueuelen 0  (Ethernet)
        RX packets 8  bytes 656 (656.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

查看下Win 10 的网卡和IP,(只贴出与Centos通信的网卡的信息),Win 10 IP为192.168.1.135。

无线局域网适配器 WLAN:

   连接特定的 DNS 后缀 . . . . . . . :
   本地链接 IPv6 地址. . . . . . . . : fe80::d9ab:19ac:60d:8c5d%19
   IPv4 地址 . . . . . . . . . . . . : 192.168.1.135
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : 192.168.1.1

结合上面的网络拓扑,现在如果我想让Win 10与dockers通信是不成功的,因为Win 10 不知道到172.19.0.0/16的路由,只能把数据包发送给路由器一,但是路由器一也不知道到172.19.0.0/16的路由,所以不能ping通。

为了解决这个问题,只需要告诉Win 10 或 路由器一 到172.19.0.0/16的路由就好,而知道这个路由的设备就是我们的Centos,所以把172.19.0.0/16到Win 10 或 到路由器一的数据包转发给Centos(192.168.1.237)就可以了。

具体解决方案:

在Win 10 中添加静态路由:

route add 172.19.0.1/16 192.168.1.237

然后在Win 10下ping某个容器的ip可以ping通:

C:\WINDOWS\system32>ping 172.19.0.2

正在 Ping 172.19.0.2 具有 32 字节的数据:
来自 172.19.0.2 的回复: 字节=32 时间=1ms TTL=63
来自 172.19.0.2 的回复: 字节=32 时间=1ms TTL=63
来自 172.19.0.2 的回复: 字节=32 时间<1ms TTL=63
……

(在路由器一中添加路由的方法我没有尝试;另外,文章开头的参考方案中需要删除宿主机内的一条iptables,但是我没有删除成功,删除以后反而失败了,具体原因还不清楚)

猜你喜欢

转载自www.cnblogs.com/Jing-Wang/p/10848960.html