zhangguanzhang's Blog

docker容器网络互联

字数统计: 1.2k阅读时长: 5 min
2017/12/23

官方文档说–link将来会被废弃,而且确实很鸡肋,有时候还要进去容器改东西。
在 1-2 年前,Docker 所有容器都连接于默认的桥接网络上,也就是很多老文章鼓捣的 docker0 桥接网卡。因此实际上默认情况下所有容器都是可以互联的,没有隔离,当然这样安全性不好。而服务发现,是在这种环境下发展出来的,通过修改容器内的 /etc/hosts 文件来完成的。凡是 --link 的主机的别名就会出现于 /etc/hosts 中,其地址由 Docker 引擎维护。因此容器间才可以通过别名互访。
但是这种办法并不是好的解决方案,Docker 早在一年多以前就已经使用自定义网络了。在同一个网络中的容器,可以互联,并且,Docker 内置了 DNS,容器内的应用可以使用服务名、容器名、别名来进行服务发现,名称会经由内置的 DNS 进行解析,其结果是动态的;而不在同一网络中的容器,不可以互联。
因此,现在早就不用 --link 了,而且非常不建议使用。
首先是因为使用 --link 就很可能还在用默认桥接网络,这很不安全,所有容器都没有适度隔离,用自定义网络才比较方便互联隔离。
其次,修改 /etc/hosts 文件有很多弊病。比如,高频繁的容器启停环境时,容易产生竞争冒险,导致 /etc/hosts 文件损坏,出现访问故障;或者有些应用发现是来自于 /etc/hosts 文件后,就假定其为静态文件,而缓存结果不再查询,从而导致容器启停 IP 变更后,使用旧的条目而无法连接到正确的容器等等。

这里写下规范的容器互联方法

1
2
3
4
5
6
[root@guan ~]# cat /etc/redhat-release 
CentOS Linux release 7.3.1611 (Core)
[root@guan ~]# uname -a
Linux guan 3.10.0-514.26.2.el7.x86_64 #1 SMP Tue Jul 4 15:04:05 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
[root@guan ~]# docker --version
Docker version 17.09.1-ce, build 7390fc6

第一种是加到同一个网络里
默认下容器ping互相不通,但是看见其他人低版本可以ping通

1
2
3
4
5
6
[root@guan ~]# docker run -tid --rm --name busybox1 busybox
8263e4e35a43eaf8cdf739f899c54dba6f6df021c12203df6d4c2474034ee71e
[root@guan ~]# docker run -tid --rm --name busybox2 busybox
891d6e2ea9da1ea6a834e2ff305d3c0d7edae8ccc3a869a2fb16319557681687
[root@guan ~]# docker exec -ti busybox1 ping busybox2
ping: bad address 'busybox2'

然后指定下默认网卡依然ping不同

1
2
3
4
5
6
7
8
9
[root@guan ~]# docker stop busybox{1,2}
busybox1
busybox2
[root@guan ~]# docker run -tid --rm --network bridge --name busybox1 busybox
72d7262cf948977172d702543ce397b92e69973ef73b279ed92b08dbb509c93c
[root@guan ~]# docker run -tid --rm --network bridge --name busybox2 busybox
0c17ca7aaf8c4c73c2b0c0ef86481777882c55e81532efb41285a679e837cced
[root@guan ~]# docker exec -ti busybox1 ping busybox2
ping: bad address 'busybox2'

然后创建个网卡后ping

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@guan ~]# docker network create guan
3df83344eec769921a902f1d5fb2f7ca1657e395d4d64b6ec5f4f6f418a5cf84
[root@guan ~]# docker run -tid --rm --network guan --name busybox1 busybox
7777391971da50058d9c71500ecfb9fadc017b7c0ab8e7d6f76307fa89446200
[root@guan ~]# docker run -tid --rm --network guan --name busybox2 busybox
f8031e09460236e848a0ad2cfdaa7fc4609301c6e86d21a38b93a23d058de183
[root@guan ~]# docker exec -ti busybox1 ping busybox2
PING busybox2 (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.082 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.19.0.3: seq=2 ttl=64 time=0.083 ms
64 bytes from 172.19.0.3: seq=3 ttl=64 time=0.080 ms
64 bytes from 172.19.0.3: seq=4 ttl=64 time=0.084 ms
64 bytes from 172.19.0.3: seq=5 ttl=64 time=0.095 ms
^C
--- busybox2 ping statistics ---
6 packets transmitted, 6 packets received, 0% packet loss
round-trip min/avg/max = 0.080/0.084/0.095 ms

第二种是使用container网络模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@guan ~]# docker run -tid --rm --name busybox1 --network guan busybox
b5f90fdea485900e0c779f904a894b9d2d79c4213472d5c81defcaf2e002396a
[root@guan ~]# docker run -tid --rm --name busybox2 --network container:busybox1 busybox
da90d737ad2f5b08914a1ac35e19a9f47c153d04cbe87499e4e1ea7c99ff5baf
[root@guan ~]# docker exec -ti busybox2 ping busybox1
PING busybox1 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.034 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.056 ms
64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.051 ms
64 bytes from 172.19.0.2: seq=3 ttl=64 time=0.056 ms
^C
--- busybox1 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.034/0.049/0.056 ms
[root@guan ~]# docker inspect busybox1 --format '{{.NetworkSettings.Networks.guan.IPAddress}}'
172.19.0.2
[root@guan ~]# docker inspect busybox2 --format '{{.NetworkSettings.Networks.guan.IPAddress}}'
<no value>

container模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。

总结,如果第一种方法的话可能低版本互相能通,但是最好是创建一张网卡后使用网卡来互联

另外容器的网络实现可以参考下面的链接
linux网络虚拟化:network namespace 简介

CATALOG