服务器的基本网络
Lo: 表示本机回环地址
eth0: 表示阿里云内网(私网)地址
docker0: 表示docker的网络地址(Docker的网卡),只要安装了Docker就会有的。
理解Docker0
Docker0就是docker 的网卡,只要安装了Docker就会自带Docker0。
Docker如何处理容器网络访问?
思考问题:我们宿主机是如何和docker容器进行网络通信,意思就是docker如何处理容器网络访问?
例如:我们在docker 上面运行运行了一个项目,访问项目需要先经过宿主机,再由到容器里面的。
先查看本机网络环境: ip addr
运行一个容器
docker run -d --name mycentos01 centos /bin/sh -c “while true;do echo ymb;sleep 20;done”;
[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fcf812b93aef centos "/bin/bash" 2 hours ago Up 2 hours mycentos02
15fdfd378264 centos "/bin/sh -c 'while t…" 2 hours ago Up 2 hours mycentos01
查看容器里面的网络 docker exec -it 容器ID ip addr
[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker exec -it 15fdfd378264 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
发现容器启动会得到一个新的网络地址:14: eth0@if15 ip地址:172.18.0.2 这个是由docker0所分配的
这时候我们再次查看宿主机的网络。发现宿主机也新增加了一个网络地址。
ip addr
[root@iZ2ze4zc54bfy36wjglfqsZ ~]# ip addr
15: vethb45f56f@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether fe:c2:fe:1a:50:5d brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::fcc2:feff:fe1a:505d/64 scope link
valid_lft forever preferred_lft forever
我们由下面的图可以知道 宿主机上面的也产生了 15: vethb45f56f@if14 网络地址。发现这两个网卡居然是一对的。
我们再次启动一个容器测试
docker run -d --name mycentos02 centos /bin/sh -c "while true;do echo hel;sleep 10;done;"
[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fcf812b93aef centos "/bin/bash" 2 hours ago Up 2 hours mycentos02
查看容器网络
[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker exec -it fcf812b93aef ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
我们会发现出现:16: eth0@if17 ip为:172.18.0.3 网卡
这个时候我们再次查看宿主机里面的网卡地址
[root@iZ2ze4zc54bfy36wjglfqsZ ~]# ip addr
17: veth8d0f47d@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 32:ab:7e:22:70:82 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::30ab:7eff:fe22:7082/64 scope link
valid_lft forever preferred_lft forever
我们会发现:宿主机里面的也是存在 17: veth8d0f47d@if16 网卡
这就是证明这些网卡是一对对出现的,并且相互绑定。
这个时候我们思考一个问题:宿主机Linux能不能 ping 容器内部呢?
经过实验:答案是可以ping通的。
思考一个问题:为什么Linux能够可以 ping 通 docker 容器内部?
原理:我们每启动一个docker容器,docker就会给docker容器分配一个ip(网络地址:172.18.0.2),其次是docker0,我们只要安装了docker,就会有一个网卡docker0,而这个docker0使用的是Linux的桥接模式,使用的技术veth-pair技术!
什么是veth-pair技术?
在上面我们发现容器带来的网卡和宿主机是一对对的。
veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连接着协议,一端彼此相连
正是因为有这个特性,veth-pair 充当一个桥梁,连接各种虚拟网络设备。
例如:Docker容器之间的连接。
我们再次测试一下:mycentos01 和 mycentos02 能否相互ping通呢?
答案是可以pinh通的。
绘画一个网络图:大家就知道是什么意思了。
结论:mycentos01 和 mycentos02 是公用一个路由器(网络),就是docker0,通过docker0来转发,所有的容器不指定网络的情况下,都是docker0 路由的,docker会给我们的容器分配一个默认可用IP地址。
关于docker网络的小结:
Docker使用的是Linux的桥接,宿主机中是一个Docker容器的网桥 就是Docker0
Docker中的所有网络接口都是虚拟的。虚拟的转发效率高!
只要删除容器,对应的网桥(网卡)一对就自动消除。
因为每启动一个容器,Docker会分配一个IP,如果项目重启了,容器之间网络就无法ping通了。
问题:我们能不能通过容器名去ping 通网络呢?
查看运行容器
docker ps
我们尝试一下 使用mycentos01 ping mycentos02 ? 答案:ping 不通如何解决呢?--link 命令
我们再启动一个容器 mycentos04,使04 和 02 之间可以相互 ping 通网络
启动容器
[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker run -d --name mycentos04 --link mycentos02 centos /bin/sh -c "while true;do echo hello;sleep 20;done"[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker exec -it mycentos04 ping mycentos02
我们发现是可以 ping 通的,如果反过来 mycentos02 也可以 ping 通mycentos04,那就可以相互通讯了,不需要经过ip。
再一次尝试 反向 ping 通网络[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker exec -it mycentos02 ping mycentos04
ping: mycentos04: Name or service not known
结果:发现mycentos02 无法 ping 通 mycentos04为什么反向无法ping通呢?
查看一下容器 mycentos04的网络
[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker exec -it mycentos04 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.3 mycentos02 fcf812b93aef
172.18.0.5 80458d723997我们发现在容器 mycentos04中的hosto 文件中配置了 mycentos02,意思就是你在访问mycentos02 容器使用,经过hosts文件转发,好比你在windows 系统 system32/ etc/hosts 文件 配置了 127.0.0.1 www.baidu.com 一样。
这是时候 我们可以看一下 mycentos02的网络配置 就知道了为什么无法 ping 通 mycentos04
[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker exec -it mycentos02 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.3 fcf812b93aef
(本质探究)这时候我们发现:mycentos02里面是没有 mycentos04 转发配置的,所以无法ping通。我们可以通过命令
docker network ls[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
bac2fa49ec66 bridge bridge local
064163c429d0 host host local
2d78385bb383 none null local
其中 bridge 表示 桥接 模式。docker 使用的就是Link的桥接。[root@iZ2ze4zc54bfy36wjglfqsZ ~]# docker network inspect bac2fa49ec66
我们发现每启动一个容器,那么相关的容器IP地址都会记录在这里里面。
总结: 由于docker0 不支持 容器名链接访问,所以现在一般不使用 --link 以及 docker0,现在使用docker 自定义网络。
下一文章:Docker的自定义网络配置。