美文网首页
Docker 网络 (二)

Docker 网络 (二)

作者: wayyyy | 来源:发表于2020-01-17 23:04 被阅读0次

容器与外部网络的访问,这里涉及2个问题:

  1. 容器访问外部世界
  2. 外部世界访问容器
容器访问外部世界
root@JD:~# 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 DOCKER -i docker0 -j RETURN

在 NAT 表中,有这么一条规则:
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
其含义是:如果网桥 docker0 收到来自 172.17.0.0/16 网段的外出包,把它交给 MASQUERADE 处理。而 MASQUERADE 的处理方式是将包的源地址替换成 host 的地址发送出去,即做了一次网络地址转换(NAT)

  • 容器内ping百度

    root@JD:~# docker run -it busybox
    / # ping www.baidu.com
    PING www.baidu.com (106.120.159.141): 56 data bytes
    64 bytes from 106.120.159.141: seq=0 ttl=48 time=27.228 ms
    64 bytes from 106.120.159.141: seq=1 ttl=48 time=27.242 ms
    64 bytes from 106.120.159.141: seq=2 ttl=48 time=27.172 ms
    64 bytes from 106.120.159.141: seq=3 ttl=48 time=27.263 ms
    64 bytes from 106.120.159.141: seq=4 ttl=48 time=27.083 ms
    64 bytes from 106.120.159.141: seq=5 ttl=48 time=27.147 ms
    
  • 在docker0上抓icmp

    root@JD:~# tcpdump -i docker0 -n icmp
    tcpdump: verbose output suppressed, use -v or -vv for full protocol   decode
    listening on docker0, link-type EN10MB (Ethernet), capture size   262144 bytes
    22:53:51.665408 IP 172.17.0.2 > 106.120.159.142: ICMP echo   request, id 1536, seq 0, length 64
    22:53:51.693649 IP 106.120.159.142 > 172.17.0.2: ICMP echo   reply, id 1536, seq 0, length 64
    22:53:52.665515 IP 172.17.0.2 > 106.120.159.142: ICMP echo   request, id 1536, seq 1, length 64
    22:53:52.693792 IP 106.120.159.142 > 172.17.0.2: ICMP echo   reply, id 1536, seq 1, length 64
    
  • 在eth0上抓icmp

    root@JD:~# tcpdump -i eth0 -n icmp
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
    22:53:54.665744 IP 192.168.0.3 > 106.120.159.142: ICMP echo request, id 1536, seq 3, length 64
    22:53:54.693804 IP 106.120.159.142 > 192.168.0.3: ICMP echo reply, id 1536, seq 3, length 64
    22:53:55.665827 IP 192.168.0.3 > 106.120.159.142: ICMP echo request, id 1536, seq 4, length 64
    22:53:55.693894 IP 106.120.159.142 > 192.168.0.3: ICMP echo reply, id 1536, seq 4, length 64
    

    docker0 收到 容器 的 ping 包,源地址为容器 IP 172.17.0.2,这没问题,交给 MASQUERADE 处理,ping 包的源地址变成了eth0 的 IP 192.168.0.3

  • 处理步骤:

    1. 容器发送 ping 包:172.17.0.2 > www.baidu.com
    2. docker0 收到包,发现是发送到外网的,交给 NAT 处理。
    3. NAT 将源地址换成 eth0的 IP:192.168.0.3 > www.baidu.com
    4. ping 包从 eth0 发送出去,到达 www.baidu.com

外部世界访问容器

docker 可将容器对外提供服务的端口映射到 host 的某个端口,外网通过该端口访问容器。

root@JD:~# docker run -d -p 80 httpd
92854d59dfa5c7311603df918d102c3d0da4373678d2ab3d835185a5392b666e
root@JD:~# docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                   NAMES
92854d59dfa5        httpd               "httpd-foreground"   5 seconds ago       Up 4 seconds        0.0.0.0:32768->80/tcp   epic_joliot
root@JD:~# curl 192.168.0.3:32768
<html><body><h1>It works!</h1></body></html>

每一个映射的端口,host 都会启动一个 docker-proxy 进程来处理访问容器的流量。

root@JD:~# ps -aux | grep docker-proxy
root     21849  0.0  0.0 108196  2608 ?        Sl   23:20   0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 32768 -container-ip 172.17.0.2 -container-port 80
root     22119  0.0  0.0  14224   976 pts/2    S+   23:21   0:00 grep --color=auto docker-proxy
  • 处理步骤
    1. docker-proxy 监听 host 的 32773 端口。
    2. 当 curl 访问 10.0.2.15:32773 时,docker-proxy 转发给容器 172.17.0.2:80。
    3. httpd 容器响应请求并返回结果。

相关文章

网友评论

      本文标题:Docker 网络 (二)

      本文链接:https://www.haomeiwen.com/subject/kwvhzctx.html