如何將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,但是我沒有刪除成功,刪除以后反而失敗了,具體原因還不清楚)

另外,雖然已經ping通,但是在我的使用場景下,telnet端口還是不通,最后無奈關閉了我的宿主機的防火牆,很不優雅,以后再解決吧,也希望有大神提供解決方案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM