端口映射
1.就是把容器的端口映射為宿主機的一個隨機或者特定端口
2.使得外部用戶可以訪問容器服務
3.本質其實就是在底層做了iptables地址轉發
4.出去的流量是做SNAT原地址轉發
5.進來的流量是做DNAT目標地址轉發
分為四種情況:
1.隨機映射,就是把容器的端口隨機映射為宿主機的一個端口 -P --publish-all
2.特定映射,映射為宿主機的特定端口 -p
3.特定映射,映射為宿主機的特定網卡的隨機端口 -p
4.特定映射,映射為宿主機的特定網卡的特定端口 -p
例子1:隨機映射 -P #-P是把容器內的所有端口隨機映射為宿主機的隨機端口
[root@ken1 ~]# docker run -d -P httpd
例子2:特定映射,映射為宿主機的特定端口
[root@ken1 ~]# docker run -d -p 81:80 httpd #注意-p后面順序 宿主機端口:容器端口
例子3:特定映射,映射為宿主機的特定網卡的隨機端口
[root@ken1 ~]# docker run -d -p 192.168.64.5::80 httpd
例子4:特定映射,映射為宿主機的特定網卡的特定端口 -p
[root@ken1 ~]# docker run -d -p 192.168.64.5:82:80 httpd
端口映射分析:
每一個映射的端口,host 都會啟動一個 docker-proxy 進程來處理訪問容器的流量:
[root@ken3 ~]# ps aux | grep docker-proxy
root 3414 0.0 0.1 364368 7040 ? Sl 22:29 0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 56 -container-ip 172.17.0.3 -container-port 80
以 0.0.0.0:32773->80/tcp 為例分析整個過程:
1. docker-proxy 監聽 host 的 32773 端口。
2. 當 curl 訪問 10.0.2.15:32773 時,docker-proxy 轉發給容器 172.17.0.2:80。
3. httpd 容器響應請求並返回結果。
底層依然是iptables:
[root@ken3 ~]# 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.18.0.0/16 ! -o br-060b813f7eeb -j MASQUERADE -A POSTROUTING -s 192.168.6.0/24 ! -o br-1f44876ac489 -j MASQUERADE -A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 80 -j MASQUERADE -A DOCKER -i docker0 -j RETURN -A DOCKER -i br-060b813f7eeb -j RETURN -A DOCKER -i br-1f44876ac489 -j RETURN -A DOCKER ! -i docker0 -p tcp -m tcp --dport 56 -j DNAT --to-destination 172.17.0.3:80