Docker容器訪問外部世界

Docker網絡(host、bridge、none)詳細介紹

Docker容器間通信

前面我們已經解決了容器間通信的問題,接下來討論容器如何與外部世界通信。

這裏涉及兩個方向:

(1)容器訪問外部世界。

(2)外部世界訪問容器。

容器訪問外部世界

在我們當前的實驗環境下,docker host是可以訪問外網的

我們看一下容器是否也能訪問外網呢?

可見,容器默認就能訪問外網。
請注意:這裏外網指的是容器網絡以外的網絡環境,並非特指Internet.

現象很簡單,但更重要的:我們應該理解現象下的本質。


在上面的例子中,busybox位於dockero這個私有bridge網絡中(172.17.0.0/16),當busybox從容器向外ping時,數據包是怎樣到達bing.com的呢?


這裏的關鍵就是NAT,我們查看一下docker host上的iptables規則

在NAT表中,有這麼一條規則:

-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

其含義是:如果網橋docker0收到來自172.17.0.0/16網段的外出包,把它交給MASQUERADE處理。而且MASQUERADE的處理方式是將

包的原地址替換成host的地址發送出去,機 做了一次網絡地址轉換(NAT)


下面我們通過tcpdump查看地址是如何轉換的。先查看docker host的路由表

默認路由通過ens192發出去,所以我們同時要監控ens192和docker0上的icmp(ping)的數據包。

當busybox ping www.baidu.com時,tcpdumo輸出如下

tcpdump -i docker0 -n icmp

docker0收到busybox的ping包,源地址爲容器的IP:172.17.0.2,這沒問題,交給MASQUERADE處理。這時,在看ens192的變化。

ping包的源地址變成ens192的192.168.1.100

這就是iptables的NAT規則的處理結果,從而保證數據包能夠到達外網。

下面這張圖來說明結果。

  • (1)busybox發送ping包:172.17.0.2 > www.bing.com。
  • (2)dockero收到包,發現是發送到外網的,交給NAT處理。
  • (3)NAT將源地址換成ens192的IP:10.0.2.15 >www.bing.com.
  • (4)ping從 ens192出去,達www.bing.como

通過NAT,docker實現了容器對外網的訪問。

 

外部世界訪問容器

下面我們來討論另一個方向:外網如何訪問到容器?
答案是:端口映射。


docker可將容器對外提供服務的端口映射到host的某個端口,外網通過該端口訪問容器。容器啓動時通過-p參數映射端口

[root@kvm ~]# docker run -d -p 80 httpd
6b89d7e3f47a425256af6934689c0009fbbad9099bf31c2e6148a6cb236a9655
[root@kvm ~]# docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                   NAMES
6b89d7e3f47a        httpd               "httpd-foreground"   5 seconds ago       Up 2 seconds        0.0.0.0:32768->80/tcp   stoic_bartik
78de9710bce0        busybox             "sh"                 19 minutes ago      Up 19 minutes                               hei
[root@kvm ~]# docker port 6b89d7e3f47a
80/tcp -> 0.0.0.0:32768

容器啓動後,可通過docker ps或者docker port查看到host映射的端口。在上面的例子中,httpd容器的80端口被映射到host 32768上,這樣就可以通過<host ip>:<32773>訪問容器的Web服務了

除了映射動態端口,也可在-p中指定映射到host某個特定端口,例如可將80端口映射到host的8080端口

[root@kvm ~]# docker run -d -p 8080:80 httpd
8d7db7b2c7a6fc03cd219d6d3c07f15261d8a12efda3be25fdb60576c91c1a7e
[root@kvm ~]# curl 192.168.1.100:8080
<html><body><h1>It works!</h1></body></html>
[root@kvm ~]# 

每一個映射的端口,host都會啓動一個docker-proxy進程來處理訪問容器的流量。

以0.0.0.0:32773-280/tcp爲例分析整個過程

  • (1)docker-proxy監聽host的32773端口。
  • (2)當curl訪問10.0.2.15:32773時,docker-proxy轉發給容器172.170.2:80。
  • (3)httpd容器響應請求並返回結果。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章