四、Docker0#
Docker网络的核心是Docker0
通过ip addr
可以看到服务器中如下几块网卡
查看公网ip可以在控制台获取或者执行:curl cip.cc
4.1、小实验1:#
Docker中启动Nginx容器,问宿主机能通过容器的ip地址ping通它吗?
# 运行镜像 [root@VM-0-15-centos ~]# docker run -d -P --name nginx1 nginx # 检查容器是否运行起来了 [root@VM-0-15-centos ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 962cf239325d nginx "/docker-entrypoint.…" 5 seconds ago Up 3 seconds 0.0.0.0:32768->80/tcp nginx1 # 进入容器中 [root@VM-0-15-centos ~]# docker exec -it nginx1 /bin/bash # 查看容器ip地址 root@962cf239325d:/# 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.17.0.2 962cf239325d # 退出容器 root@962cf239325d:/# exit exit # ping [root@VM-0-15-centos ~]# ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.064 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.059 ms 64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.056 ms c64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.058 ms
实验结果很明显:可以ping通!
为什么能ping通呢???
查看容器和宿主机网卡的信息就知道了
宿主机中有一块叫Docker0的网卡如下,它的网络段172.17.0.1/16
容器的网卡信息如下:
可以看到这宿主机和容器其实是在同一个网段的~,所以肯定能通!
4.2、小实验2:#
如果我宿主机上的容器中同时运行两个容器,问:
这两个容器之间能通过彼此的ip的相互ping通吗?
# 检查两个容器是否都运行起来了 [root@VM-0-15-centos ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d37b518465a0 tomcat "catalina.sh run" 2 seconds ago Up 2 seconds 0.0.0.0:32772->8080/tcp tomcat2 85859d226c8c f796d3d2c195 "catalina.sh run" 17 minutes ago Up 17 minutes 0.0.0.0:32771->8080/tcp tomcat1 # 查看记录tomcat1的ip [root@VM-0-15-centos ~]# docker exec -it tomcat1 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 184: eth0@if185: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever # 查看记录tomcat2的ip [root@VM-0-15-centos ~]# docker exec -it tomcat2 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 186: eth0@if187: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever # 使用tomcat2 ping tomcat1 [root@VM-0-15-centos ~]# docker exec -it tomcat2 ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.089 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.066 ms 64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.072 ms ^C --- 172.17.0.2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 0.066/0.075/0.089/0.014 ms # 使用tomcat1 ping tomcat2 [root@VM-0-15-centos ~]# docker exec -it tomcat1 ping 172.17.0.3 PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data. 64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.069 ms 64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.061 ms 64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.070 ms 64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.070 ms ^C
结论很明显:彼此之间能ping通!
那Docker是怎么做的呢?
我们安装Docker后会带有一个默认的网卡叫做Docker0,它实际上是一个网桥,其中有一端连接在真实的互联网上,使用的的技术是veth-pair桥接技术
此时我的Docker中已经运行了两个容器了,现在去看下宿主机和两个容器的网卡信息。
宿主机:
tomcat1:
tomcat2:
仔细看如上两图中多出来的网卡命名对应关系
# 宿主机多出来的: 185: veth79ccfd1@if184 # 对应容器tomcat1: 184: eth0@if185 # 宿主机多出来的: 187: vethac83886@if186 # 对应容器tomcat2: 186: eth0@if187
这种网卡成对对应的关系,就是借助veth-pair技术实现的
veth-pair就是一对虚拟的网络接口,成对出现,一端连着协议,一端彼此相连。由它充当一个桥梁的作用,连接各个Docker 容器,实现网络数据交互
在当前的案例中之间能Ping的
在不指定容器网络的情况下,默认容器使用的Docker0做网桥
通过下面的命令查看使用Docker0的所有Container
Docker会为容器分配一个可用的ip
分配的ip都在上图规定的subnet子网网段下的格式:172.17.0.2/16
在上面划分子网时有提到这种划分的方式,最后的16为它的网络号,也就是说他还有16位的机器号,也就是2的16次方-2个
五、Docker网络 --link#
前面的验证了Docker两个不同的容器可以通过ip直接ping通
--link 可以让我们让两个容器通过服务名直接ping通
# 使用--link这个启动参数,连通不同的容器,实现通过服务名就ping通容器 [root@VM-0-15-centos ~]# docker run -d -P --name tomcat3 --link tomcat2 tomcat 2d8c1363094cd2e09bcd3d3a4e85e0864f32718d38aa4dab9640522c4ea3a87a # 检查容器是否正常启动了 [root@VM-0-15-centos ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2d8c1363094c tomcat "catalina.sh run" 2 seconds ago Up 2 seconds 0.0.0.0:32773->8080/tcp tomcat3 d37b518465a0 tomcat "catalina.sh run" About an hour ago Up About an hour 0.0.0.0:32772->8080/tcp tomcat2 85859d226c8c f796d3d2c195 "catalina.sh run" About an hour ago Up About an hour 0.0.0.0:32771->8080/tcp tomcat1 # 使用tomcat3ping通tomcat2 [root@VM-0-15-centos ~]# docker exec -it tomcat3 ping tomcat2 PING tomcat2 (172.17.0.3) 56(84) bytes of data. 64 bytes from tomcat2 (172.17.0.3): icmp_seq=1 ttl=64 time=0.093 ms 64 bytes from tomcat2 (172.17.0.3): icmp_seq=2 ttl=64 time=0.068 ms 64 bytes from tomcat2 (172.17.0.3): icmp_seq=3 ttl=64 time=0.069 ms c64 bytes from tomcat2 (172.17.0.3): icmp_seq=4 ttl=64 time=0.067 ms ^C --- tomcat2 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 0.067/0.074/0.093/0.012 ms # 反向使用tomcat2 ping tomcat3 [root@VM-0-15-centos ~]# docker exec -it tomcat2 ping tomcat3 ping: tomcat3: Name or service not known
原理:--link实际上是修改了tomcat3的host文件,如下
[root@VM-0-15-centos ~]# docker exec -it tomcat3 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.17.0.3 tomcat2 d37b518465a0 172.17.0.4 2d8c1363094c
而tomcat2的host文件中没有这种别名,所以反向通过服务名不能ping通