none模式的好处是可以静态配置IP地址,也就是我们可以自己手工去配置IP,不用DHCP去分配,none模式有自己的网络模块,默认是没有指定IP地址需要人工去指定,bridge模式用的是最多的模式,该模式下会为每个容器分配其IP地址。
eth0是宿主机的IP地址10.10.101.105,docker0相当于二层的交换机,docker1或者docker2叫做容器(虚拟机),多个容器的网络连接到交换机上(docker0相当于二层的交换机),从而能够实现容器和容器之间是可以访问的,因为在二层网络里面,docker0能够自动学习局域网的mac地址,并将请求转发到对应的网口。交换机是在一个网段当中,二层交换机只有一个网络,默认的网段是172.17.0.1网段。
[root@www my_wordpress]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:b4ff:fe35:f546 prefixlen 64 scopeid 0x20<link>
ether 02:42:b4:35:f5:46 txqueuelen 0 (Ethernet)
RX packets 27705 bytes 27905546 (26.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 38270 bytes 339811508 (324.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#docker0是一张网卡也是一个交换机,docker0是什么网段,那么容器dhcp分配到的iP就是什么网段
ip加掩码来判断是否在一个网络内部 判断交换机和容器
#在同一个网段只能docker之间的通信不需要路由(网关),docker1容器和docker2容器通信只在交换机里面通信,不需要路由,可以找到对方的mac(通过ARP广播找到对方ip),容器和宿主机通信就需要走路由
启动docker引擎就会在宿主机上面添加docker0,docker0既是网卡也是网桥,所以有两重身份。创建容器会创建一对虚拟网卡设备叫veth pair
(1)首先宿主机上创建一对虚拟网卡veth pair设备,veth设备总是成对出现的,组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来,veth设备常用来连接两个网络设备。一对虚拟网卡veth pair设备
[root@localhost ~]# docker run -itd centos7-ssh
47e140d183836ab7293c35e1c7ed0b67339c45f03b34a82aa3057607e547f97e
[root@localhost ~]# ifconfig
vethaa94037: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::bce0:bdff:fe06:4d24 prefixlen 64 scopeid 0x20<link>
ether be:e0:bd:06:4d:24 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7 bytes 578 (578.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
你会发现启动一个容器就多了一个网卡,这个网卡是放在宿主机上面,eth0是放在容器里面。
(2)Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0,然后将另一端放在宿主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过brctl show命令查看。
创建一个容器,创建容器的时候会创建两个网卡,一个网卡放在容器里面,命名为eth0,一个放在宿主机命名为veth。veth是一种技术相当于网线的两端,那么宿主机上的docker0就可以和容器里面的eth0进行通信了,veth在宿主机,eth0在容器当中
创建多个容器就会产生多个veth网卡,创建10个容器就会多出10个veth*网卡,要将veth看作类似和网口一样的,相当于dcoker0交换机的一个网口
[root@www my_wordpress]# yum install bridge* -y
[root@www my_wordpress]# brctl show
bridge name bridge id STP enabled interfaces
br-aa9c38324b49 8000.0242b444614d no veth200ffc6
veth8575b7b
docker0 8000.0242b435f546 no
[root@www my_wordpress]# ifconfig | grep veth
veth200ffc6: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
veth8575b7b: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
#可以看到网桥交换机有2个网卡,因为我启动了2个容器,brctl可以帮助你看到哪些设备是连接到交换机上面的
[root@www my_wordpress]# docker ps | grep -i up | wc -l
2
这个主要是实现容器和宿主机的通信的,将veth加入网桥交换机docker0,主要是容器就可以在一个网段里面了,就在一个二层交换机上面了,在二层交换机上面容器就可以互相访问了。
(3)从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。
(4)此时容器IP与宿主机能够通信,宿主机也可以访问容器中的IP地址,在Bridge模式下,连在同一网桥上的容器之间可以相互通信,同时容器也可以访问外网,但是其他物理机不能访问docker容器IP,需要通过NAT将容器IP的port映射为宿主机的IP和port。
[root@localhost ~]# docker run -itd centos7-ssh
3e1dbc9ea196401b36842812cb3dfb9ddd351fe986c680a9c097a58912191093
[root@localhost ~]# ifconfig
vethc42c5bc: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::9c6d:b1ff:feeb:1984 prefixlen 64 scopeid 0x20<link>
ether 9e:6d:b1:eb:19:84 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7 bytes 578 (578.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#可以看到vethc42c5bc网卡 9e:6d:b1:eb:19:84和 eth0网卡02:42:ac:11:00:02 MAC地址是不一样的
[root@localhost ~]# docker exec -it 3e1dbc9ea196 /bin/bash
[root@3e1dbc9ea196 ansible]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 8 bytes 648 (648.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#docker0的ip地址为容器的网关
[root@f49833e1e876 ansible]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
容器可以访问外网,但是其他的物理机不能访问docker容器的IP的,如果外面物理机想要访问容器想要run -itd -p端口号 这相当于做了地址转换DNAT。
外网是不能之间访问容器IP的,因为容器IP是内网IP,只有宿主机是相通的,veth是不需要IP的,可以将其看作接口,看作交换机上面的接口,数据可以从一端进来,可以从一端出去。
为什么要将容器的网关设置为docker0的IP地址呢,这样做的目的是容器要上网,先将数据发送给docker0网卡,通过它去上网,docker0网卡虽然和外网不通,但是和ens33网卡是相通的,通过转发ens33来上网。
容器的网关地址为docker0的IP地址主要是为了将数据发个docker0,容器不能之间将数据发给物理网卡,因为容器在一个网段,宿主机又在另外一个网段,压根不通,docker0通过ens33将数据转发出去的
docker0相对于宿主机来说是另外一块网卡,ens33相对于连接着网线,但是docker0没有连接网线,只要ens33能够上网,其他网卡就可以通过ens33将数据转发出去,docker0是通过docker引擎创建的,不上外网不需要经过ens33转发。
外网要访问容器要在宿主机做DNAT映射 端口映射-p选项,如果不做端口映射外网是访问不了容器的。
[root@localhost ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:55ff:feda:5064 prefixlen 64 scopeid 0x20<link>
ether 02:42:55:da:50:64 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5 bytes 438 (438.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@localhost ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.179.2 0.0.0.0 UG 100 0 0 ens33
[root@localhost ~]# docker exec -it b358705e0274 /bin/bash
[root@b358705e0274 ansible]# yum install traceroute -y
[root@b358705e0274 ansible]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
[root@b358705e0274 ansible]# traceroute www.baidu.com
traceroute to www.baidu.com (180.101.49.11), 30 hops max, 60 byte packets
1 gateway (172.17.0.1) 0.032 ms 0.012 ms 0.012 ms
2 192.168.179.2 (192.168.179.2) 0.169 ms 0.073 ms 0.088 ms
#可以看到是先发给docker0网卡,然后通过ens33上网