容器網路(二)docker容器訪問外部網路及對外提供服務
阿新 • • 發佈:2020-09-02
由於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 ms64 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