1. 程式人生 > 實用技巧 >容器網路(二)docker容器訪問外部網路及對外提供服務

容器網路(二)docker容器訪問外部網路及對外提供服務

由於docker容器訪問外部網路及對外提供服務都使用到iptable,我們先了解下iptable的基礎知識。

一、Iptables

1、iptables的鏈

iptables有5條預設的鏈,分別為:

  • INPUT
  • OUTPUT
  • PREROUTING
  • FORWARD
  • POSTROUTING

2、iptables的表

  • iptables有4張表,分別為:
  • filter表,負責過濾功能
  • nat表,網路地址轉換功能
  • managle表,拆解報文,做出修改,並重新封裝 的功能
  • raw表,關閉nat表上啟用的連線追蹤機

3、連結串列的關係

鏈中的規則屬於四種表的其中一種

4、常見的資料流向

  • 到本機某程序的報文:PREROUTING --> INPUT
  • 由本機轉發的報文:PREROUTING --> FORWARD --> POSTROUTING
  • 由本機的某程序發出報文(通常為響應報文):OUTPUT --> POSTROUTING

二、容器訪問外部網路

1、容器訪問外部網路是通過iptable的snat實現訪問外部網路的

# docker run -it busybox
/ # ping www.baidu.com
PING www.baidu.com (14.215.177.39): 56 data bytes
64 bytes from 14.215.177.39: seq=0 ttl=50 time=3.459 ms
64 bytes from 14.215.177.39: seq=1 ttl=50 time=3.432 ms ^C --- www.baidu.com ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 3.432/3.445/3.459 ms / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02 inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:
1500 Metric:1 RX packets:6 errors:0 dropped:0 overruns:0 frame:0 TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:989 (989.0 B) TX bytes:426 (426.0 B)

檢視nat表

# iptables -t nat -S
……

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

nat表規則表明,對於源地址為172.17.0.0/16段,出口網絡卡不是docker0的資料包進行nat轉換

2、資料包的流程圖如下

三、容器對外提供服務

1、Docker容器是通過dnat對映或docker-proxy服務對外提供訪問的

# docker run -d -p 8080:80 httpd //-p 8080:80表示將訪問宿主機8080埠的資料包轉發到容器80埠的服務。
# netstat -tlunp|grep 8080
tcp6       0      0 :::8080                 :::*                    LISTEN      11718/docker-proxy  
# iptables -S -t nat
……
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80
……
# curl "http://127.0.0.1:8080"
<html><body><h1>It works!</h1></body></html>

2、使用dnat還是docker-proxy?

先給結論

場景

轉發

外部伺服器訪問10.30.20.87:8080

通過iptables nat規則訪問

本機訪問10.30.20.87:8080

通過iptables nat規則訪問

本機訪問127.0.0.1:8080

通過docker-proxy轉發

本機上的容器訪問10.30.20.87:8080

通過docker-proxy轉發

完整的nat表

# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80

1、外部伺服器訪問10.30.20.87:8080

 匹配到DNAT規則,訪問到容器
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80

2、本機訪問10.30.20.87:8080

匹配到DNAT規則,訪問到容器
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j LOG --log-prefix DOCKER-DNAT

3、本機訪問127.0.0.1:8080

沒有匹配到任何iptable,走docker-proxy

4、本機上的容器訪問10.30.20.87:8080

-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A DOCKER -i docker0 -j RETURN
最後走的docker-proxy