1. Docker网络模式
Docker在创建容器时有四种网络模式,bridge为默认不需要用--net=bridge去指定,其他三种模式需要在创建容器时使用--net去指定。
Docker安装后,会自动创建三个网络,分别为bridge、host、none。可以使用以下命令查看:
ycy@ubuntu18:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
349d6173c6e8 bridge bridge local
738ff1fb9923 host host local
1abb3c2c9846 none null local
1.1 bridge模式
默认情况下,创建一个新的容器都会自动连接到bridge网络,相当于Vmware中的Nat模式。
新建容器有独立的网络命名空间,并通过以下步骤将容器接入docker0中。
(1)创建veth pari虚拟网络对(类似于网线的两头);
(2)将veth pair的一端置于主机的root network namespace中,并将其关联docker0;
(3)将veth pair的另一端置于新建容器的网络命名空间中;
(4)从docker0所在的子网中选一个可用的IP地址赋予veth pair在容器的一端。
ycy@ubuntu18:~$ docker run -d --name s1 nginx
f5e8a999d00b06d9d95ecf732c81fbf1ff6b29b5707ed0868304d7c40567cd80
ycy@ubuntu18:~$ docker inspect -f "{{ .NetworkSettings.IPAddress }}" s1
172.17.0.2
ycy@ubuntu18:~$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02422bc4b451 no veth392e4b4
1.2 host模式
相当于Vmware中的桥接模式。新建容器与宿主机共享网络命名空间,该容器不会连接到docker0中,直接使用网络的网络资源进行通信。
ycy@ubuntu18:~$ docker run -it --name v1 --network host nginx /bin/bash
root@ubuntu18:/# 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:2bff:fec4:b451 prefixlen 64 scopeid 0x20<link>
ether 02:42:2b:c4:b4:51 txqueuelen 0 (Ethernet)
RX packets 25018 bytes 1093724 (1.0 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 30033 bytes 185103642 (176.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.146.100 netmask 255.255.255.0 broadcast 192.168.146.255
inet6 fe80::badd:42b1:f38b:bf0f prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:9e:08:65 txqueuelen 1000 (Ethernet)
RX packets 231221 bytes 282634477 (269.5 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 72539 bytes 6474630 (6.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 6118 bytes 534681 (522.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6118 bytes 534681 (522.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
1.3 none模式
新建容器有独立的网络namespace,但是不会配置任何网络参数,也不会接入docker0中,用户可对其进行任意的手动配置。
ycy@ubuntu18:~$ docker run -it --name net-none --network none mynginx /bin/bash
root@65fed235fdcb:/# ifconfig
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.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
1.4 container模式
新建容器与一个已有的容器共享network namespace,该容器不会连接到docker0中,直接使用已有容器的网络资源进行通信。
joined容器是一种较为特别的网络模式
在容器创建时使用--network=container:name(name是运行的容器名)
处在这个模式下的Docker容器会共享一个网络栈,这样两个容器可以使用localhost高效快速通信。
ycy@ubuntu18:~$ docker run -it --name s1 mynginx /bin/bash
root@da6f3ecc0391:/# 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 21 bytes 2682 (2.6 KiB)
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
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.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
root@da6f3ecc0391:/# ycy@ubuntu18:~$
ycy@ubuntu18:~$ docker run -it --name s2 --network container:s1 mynginx /bin/bash
root@da6f3ecc0391:/# 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 25 bytes 3036 (2.9 KiB)
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
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.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
1.5 用户自定义网络模式
Docker提供了三种自定义网络驱动:bridge、overlay、macvlan。
bridge驱动类似于默认的bridge网络模式,但增加了一些新的功能(带DNS解析功能),overllay和macvlan适用于创建跨主机网络。
创建桥接网络
ycy@ubuntu18:~$ docker network create -d bridge --subnet 172.20.0.0/24 --gateway 172.20.0.1 br0
a765c3af4c5220534638e542d8dfa10e45e0e89c6d6f83820d0232339b35e3c7
创建bridge网络后,可以看到新增了一个网桥(172.20.0.1)。
ycy@ubuntu18:~$ ip a | grep br-
19: br-a765c3af4c52: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
inet 172.20.0.1/24 brd 172.20.0.255 scope global br-a765c3af4c52
2. Docker网络通信
2.1 同一宿主机不同网桥间的容器间的通信
创建两个自定义网络
ycy@ubuntu18:~$ docker network create -d bridge --subnet 172.20.0.0/24 --gateway 172.20.0.1 br0
f8eb445161aa2291a1f89ee7879c2825e7c9a556b1f400f78181b62f8f9ff570
ycy@ubuntu18:~$ docker network create -d bridge --subnet 172.21.0.0/24 --gateway 172.21.0.1 br1
65c9dd48d5b57d70c845fd4ce1a287cd7d4c864a6b641560efb71049ffbf4a05
创建两个测试容器,分别加入创建的网络
ycy@ubuntu18:~$ docker run -it -d --name s0 --network br0 --ip 172.20.0.100 nginx /bin/bash
e28178cb59210b488efdf00519d135609664957fd2ee32cbd28a9119ea4f566b
ycy@ubuntu18:~$ docker run -it -d --name s1 --network br1 --ip 172.21.0.100 nginx /bin/bash
1afbf57debaa8a7150243cabcebaf9628d10c328cec1c8992379f01713f80d91
将当前容器加入到需要与之通信的网络
ycy@ubuntu18:~$ docker network connect br1 s0
ycy@ubuntu18:~$ docker container attach s0
测试网络连接
root@e28178cb5921:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.20.0.100 netmask 255.255.255.0 broadcast 172.20.0.255
ether 02:42:ac:14:00:64 txqueuelen 0 (Ethernet)
RX packets 26 bytes 3106 (3.0 KiB)
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
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.21.0.2 netmask 255.255.255.0 broadcast 172.21.0.255
ether 02:42:ac:15:00:02 txqueuelen 0 (Ethernet)
RX packets 19 bytes 2462 (2.4 KiB)
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
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.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
2.2 跨主机容器间的通信
2.2.1 macvlan
- macvlan网络容器接口直接与主机网卡连接,无需NAT或端口映射。
- macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络。
- macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的。
- 可以在三层上通过网关将macvlan网络联通起来。
- docker本身不做任何限制,像传统vlan网络那样管理即可。
网卡开启混杂模式
[root@CentOS7 ~]# ip link set ens37 promisc on
创建macvlan网络
使用-d macvlan创建macvlan网络,使用-o parent指定流量在docker主机上实际通过的物理接口
[root@CentOS7 ~]# docker network create -d macvlan --subnet 172.20.0.0/24 --gateway 172.20.0.1 -o parent=ens37 macvlan1
8a36aca364caeff25642c843fc0d3064bd74a60985545954b59e0b8bc3218d3f
开启一个桥接macvlan的容器
[root@CentOS7 ~]# docker run -it --name s0 --network macvlan1 --ip 172.20.0.100 docker.io/centos
[root@e5519dccc6f2 /]#
另一个虚拟机也做类似配置
ycy@ubuntu18:~$ sudo ip link set ens38 promisc on
ycy@ubuntu18:~$ docker network create -d macvlan --subnet 172.20.0.0/24 --gateway 172.20.0.1 -o parent=ens38 macvlan1
9042e03b3242184498fc6ca2afae7953f776ec299ba8d05f21b1bbf240b32e71
ycy@ubuntu18:~$ docker run -it --name s1 --network macvlan1 --ip 172.20.0.200 nginx
root@8f8c30548017:/#
测试网络连通性