文章目录
docker(7)容器与外部通信容器访问外部世界外部世界访问容器
docker(7)容器与外部通信
容器如何与外部世界通信,这里涉及两个方向 1.容器访问外部世界 2.外部世界访问容器
容器访问外部世界
在我们当前的实验环境下 docker host是可以访问外网的
[root@server7 ~
]
PING www.baidu.com
(61.135.169.121
) 56
(84
) bytes of data.
64 bytes from 61.135.169.121
(61.135.169.121
): icmp_seq
=1 ttl
=52 time
=97.4 ms
64 bytes from 61.135.169.121
(61.135.169.121
): icmp_seq
=2 ttl
=52 time
=77.2 ms
我们看一下容器是否也能访问外网呢?
[root@server7 ~
]
/
PING www.baidu.com
(61.135.169.125
): 56 data bytes
64 bytes from 61.135.169.125: seq
=0 ttl
=51 time
=173.166 ms
64 bytes from 61.135.169.125: seq
=1 ttl
=51 time
=104.223 ms
[root@server7 ~
]
-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.22.16.0/24
! -o br-c8e9feff6d4a -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16
! -o br-2c251699942a -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER -i br-c8e9feff6d4a -j RETURN
-A DOCKER -i br-2c251699942a -j RETURN
"""
-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路由表
[root@server7 ~
]
default via 172.25.0.250 dev eth0
[root@server7 ~
]
/
PING www.baidu.com
(61.135.169.125
): 56 data bytes
64 bytes from 61.135.169.125: seq
=0 ttl
=51 time
=63.100 ms
64 bytes from 61.135.169.125: seq
=1 ttl
=51 time
=66.232 ms
64 bytes from 61.135.169.125: seq
=2 ttl
=51 time
=69.345 ms
64 bytes from 61.135.169.125: seq
=3 ttl
=51 time
=65.300 ms
[root@server7 ~
]
tcpdump: verbose output suppressed, use -v or -vv
for full protocol decode
listening on docker0, link-type EN10MB
(Ethernet
), capture size 65535 bytes
22:33:58.411204 IP 172.17.0.2
> 61.135.169.125: ICMP
echo request,
id 1280,
seq 46, length 64
22:33:58.623189 IP 61.135.169.125
> 172.17.0.2: ICMP
echo reply,
id 1280,
seq 46, length 64
22:33:59.411449 IP 172.17.0.2
> 61.135.169.125: ICMP
echo request,
id 1280,
seq 47, length 64
[root@server7 ~
]
tcpdump: verbose output suppressed, use -v or -vv
for full protocol decode
listening on eth0, link-type EN10MB
(Ethernet
), capture size 65535 bytes
22:37:28.382796 IP 172.25.0.7
> 61.135.169.121: ICMP
echo request,
id 1536,
seq 11, length 64
22:37:28.457137 IP 61.135.169.121
> 172.25.0.7: ICMP
echo reply,
id 1536,
seq 11, length 64
22:37:29.383057 IP 172.25.0.7
> 61.135.169.121: ICMP
echo request,
id 1536,
seq 12, length 64
"""
docker0收到busybox的ping包 源地址为容器IP 172.17.0.2 交给MASQUERADE 处理 在eth0上面我们看到了变化
ping包的源地址变成了eth0的IP 172.25.0.7
这就是iptable NAT规则的处理结果 从而保证数据包能够到达外网
即:
1.busybox发送ping包:172.17.0.2
>www.baidu.com
2.docker0收到包,发现是发送到外网站的,交给NAT处理
3.NAT将源地址转换成eth0的IP地址:172.25.0.7
>www.baidu.com
4.ping包从eth0发送出去,到达www.baidu.com
通过NAT,docker实现了容器对外网的访问
外部世界访问容器
外网如何访问到容器? 端口映射
docker可将容器对外提供服务的端口映射到host的某个端口,外网通过该端口访问容器,容器启动时通过-p参数映射端口
[root@server7 ~
]
59605d55848ce748f56abf3079ae3901525000602cdeaf146a778f3d558e3c4f
[root@server7 ~
]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
59605d55848c httpd
"httpd-foreground" 4 seconds ago Up 4 seconds 0.0.0.0:32768-
>80/tcp jolly_galileo
[root@server7 ~
]
80/tcp -
> 0.0.0.0:32768
[root@server7 ~
]
<html
><body
><h1
>It works
!</h1
></body
></html
>
除了映射动态端口,也可以在-p中指定映射到host某个特定端口,例如可以将80端口映射到host的8080端口
[root@server7 ~
]
b59175d1bc6f7f2aa81cd854f87aef4c786a0fa801599125caed4721deb15f62
[root@server7 ~
]
<html
><body
><h1
>It works
!</h1
></body
></html
>
[root@server7 ~
]
root 2529 2122 0 23:05 ? 00:00: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 2672 2122 0 23:11 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8080 -container-ip 172.17.0.3 -container-port 80
root 2792 2099 0 23:11 pts/0 00:00:00
grep --color
=auto docker-proxy
"""
以0.0.0.0:32773->80/tcp 为例分析整个过程
1.docker-proxy 监听host的32773端口
2.当curl访问 172.25.0.7:32773时,docker-proxy转发给容器ip:80
3.httpd容器响应请求并返回结果
"""