摘要
docker 安装的时候会自动创建三个网络,bridge、host、none,可以直接使用如下方式查看
[vagrant@localhost ~]$ docker network ls
NETWORK ID NAME DRIVER SCOPE
dae698160db2 bridge bridge local
e729badaff22 host host local
1f43eec7cc74 none null local
一、none 网络
即是没有网络的网络,没有任何网卡存在。创建容器的时候通过 --network=none 指定使用 none 网络。
- 未指定 --network=none ,网络信息如下:
[vagrant@localhost dockerfiles]$ docker run -it centos-ip [root@45debba38adb /]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 0.0.0.0 inet6 fe80::42:acff:fe11:2 prefixlen 64 scopeid 0x20<link> ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet) RX packets 7 bytes 578 (578.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 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 1 (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
- 指定 --network=none ,网络信息如下:
[vagrant@localhost dockerfiles]$ docker run -it --network=none centos-ip [root@a205054810a7 /]# ifconfig 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 1 (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
PS.封闭网络很少用到,主要应用于安全相关的模块,比如生成随机密码等信息时,我们就可以将容器放置到 none 网络中避免密码泄露。
二、host 网络
即连接到 host 网络容器,共享 Docker host 的网络栈,容器的网络配置与 host 完全一样,可以通过 --network=host 指定使用 host 网络。
[vagrant@localhost dockerfiles]$ docker run -it --network=host centos-ip [root@localhost /]# ifconfig docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0 inet6 fe80::42:3aff:fe12:c3a7 prefixlen 64 scopeid 0x20<link> ether 02:42:3a:12:c3:a7 txqueuelen 0 (Ethernet) RX packets 9785 bytes 399804 (390.4 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 10839 bytes 26628431 (25.3 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255 inet6 fe80::5054:ff:fe47:4652 prefixlen 64 scopeid 0x20<link> ether 52:54:00:47:46:52 txqueuelen 1000 (Ethernet) RX packets 122966 bytes 117316782 (111.8 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 47602 bytes 2920675 (2.7 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.10.50 netmask 255.255.255.0 broadcast 192.168.10.255 inet6 fe80::a00:27ff:fec4:c30e prefixlen 64 scopeid 0x20<link> ether 08:00:27:c4:c3:0e txqueuelen 1000 (Ethernet) RX packets 3278 bytes 417118 (407.3 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2679 bytes 519842 (507.6 KiB) 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 1 (Local Loopback) RX packets 64 bytes 5568 (5.4 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 64 bytes 5568 (5.4 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
在容器中可以看到 host 中的所有网卡。优点是:性能高;缺点是:不灵活,需要考虑端口冲突问题;
三、 bridge 网络
默认创建容器的时候都会把网络挂到 docker0 上面,查看bridge上面的网路偶设备。
[vagrant@localhost dockerfiles]$ brctl show bridge name bridge id STP enabled interfaces docker0 8000.02423a12c3a7 no [vagrant@localhost dockerfiles]$ docker run -d centos-ip [vagrant@localhost ~]$ brctl show bridge name bridge id STP enabled interfaces docker0 8000.02423a12c3a7 no veth0066151
可以看到一个新的网络接口 veth1cfcc86 被挂到docker0 上, veth1cfcc86 就是创建容器的虚拟网卡。
查看当前容器的网卡信息
[root@0d87445fd9f1 /]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe11:2/64 scope link valid_lft forever preferred_lft forever
容器中有一个网卡 eth0@if6 。另外 eth0@if6 与 veth0066151 是一对 veth pair。
查看host bridge 的网络配置如下所示:
[vagrant@localhost ~]$ docker network inspect bridge [ { "Name": "bridge", "Id": "10a34b9d8d8eadf0ffa0d20c021b523a69f3998912425204698bd95f6ca0e185", "Created": "2018-03-06T09:46:43.25542228Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] },
可以看出,bridge 的网络配置 subnet 就是172.17.0.0/16,并且网关是 172.17.0.1,即docker0.
[vagrant@localhost ~]$ ifconfig docker0 docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0 inet6 fe80::42:2eff:fec7:4a71 prefixlen 64 scopeid 0x20<link> ether 02:42:2e:c7:4a:71 txqueuelen 0 (Ethernet) RX packets 725 bytes 31185 (30.4 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 752 bytes 1438654 (1.3 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
容器创建的时候,docker 会自动从172.17.0.0/16 中分配以IP。
四、user-defined 网络
Docker提供的 user-defined 网络驱动有是那种:bridge、overlay 和 macvlan。其中后两种主要用于创建跨主机网络,我们先关注 bridge 驱动
[vagrant@localhost ~]$ docker network create --driver bridge --subnet 172.20.16.0/16 --gateway 172.20.16.1 self_net f8a6174499c8419eae50b247b5c3ec892a168375e652f7f29112e46ce910a25f [vagrant@localhost ~]$ brctl show bridge name bridge id STP enabled interfaces br-f8a6174499c8 8000.024241b80c5f no docker0 8000.02422ec74a71 no veth0066151
新建了一个bridge网络,br-f8a6174499c8, 其中 br-f8a6174499c8 为 self_net 网络的段id。
[vagrant@localhost ~]$ docker network inspect self_net [ { "Name": "self_net", "Id": "f8a6174499c8419eae50b247b5c3ec892a168375e652f7f29112e46ce910a25f", "Created": "2018-03-06T10:09:03.201425146Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.20.16.0/16", "Gateway": "172.20.16.1" } ] },
可以注意到,docker 为 self_net 分配了我们指定的网段 172.20.16.0/16。指的主要的是,当未指定 --subnet 和 --gateway 时,docker会默认自动分配一个网段。
容器使用新的网络,在容器启动的时候,通过 --network 进行指定
[vagrant@localhost ~]$ docker run -it --network=self_net centos-ip [root@1f1bf1c9c0fd /]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.20.0.1 netmask 255.255.0.0 broadcast 0.0.0.0 inet6 fe80::42:acff:fe14:1 prefixlen 64 scopeid 0x20<link> ether 02:42:ac:14:00:01 txqueuelen 0 (Ethernet) RX packets 12 bytes 1016 (1016.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 6 bytes 508 (508.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 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1 (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
同时,静态IP也可以直接通过 --ip 进行手动指定。但是只有手动指定了 --subnet 才可以指定 --ip。且指定的 ip 必须在 --subnet 网络内。
[vagrant@localhost dockerfiles]$ docker run -it --network=self_net --ip=172.19.10.10 centos-ip-new docker: Error response from daemon: Invalid address 172.19.10.10: It does not belong to any of this network's subnets.
指定正确的网络
[vagrant@localhost dockerfiles]$ docker run -it --network=self_net --ip=172.20.16.3 centos-ip-new [root@7044428bd01f /]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:14:10:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.20.16.3/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe14:1003/64 scope link valid_lft forever preferred_lft forever
- 容器间同一个网段的网络互通
继续启动一个同网络内的容器[vagrant@localhost ~]$ docker run -it --network=self_net --ip=172.20.16.4 centos-ip-new [root@3aec978eea9b /]#
两个 centos-ip-new 之间进行通讯,验证如下
[root@3aec978eea9b /]# ping -c 3 172.20.16.3 PING 172.20.16.3 (172.20.16.3) 56(84) bytes of data. 64 bytes from 172.20.16.3: icmp_seq=1 ttl=64 time=0.085 ms 64 bytes from 172.20.16.3: icmp_seq=2 ttl=64 time=0.074 ms ^C --- 172.20.16.3 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.074/0.079/0.085/0.010 ms
[root@7044428bd01f /]# ping -c 3 172.20.16.4 PING 172.20.16.4 (172.20.16.4) 56(84) bytes of data. 64 bytes from 172.20.16.4: icmp_seq=1 ttl=64 time=0.056 ms 64 bytes from 172.20.16.4: icmp_seq=2 ttl=64 time=0.059 ms 64 bytes from 172.20.16.4: icmp_seq=3 ttl=64 time=0.087 ms --- 172.20.16.4 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1999ms rtt min/avg/max/mdev = 0.056/0.067/0.087/0.015 ms
验证是可以互相通信的。
- 非同一个网络内的通信
启动一个使用默认网桥的容器[vagrant@localhost ~]$ docker run -it centos-ip-new [root@f5b592f7b940 /]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe11:2/64 scope link valid_lft forever preferred_lft forever
可以看到,网络是默认bridge 172.17.0.0/16,跟 self_net 172.20.16. 0/16 不在一个网络,理论上应该是无法通信的,我们验证如下
[root@f5b592f7b940 /]# ping -c 3 172.20.16.4 PING 172.20.16.4 (172.20.16.4) 56(84) bytes of data. --- 172.20.16.4 ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 2000ms [root@f5b592f7b940 /]# ping -c 3 172.20.16.3 PING 172.20.16.3 (172.20.16.3) 56(84) bytes of data. --- 172.20.16.3 ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 1999ms
可以看到,无法通信。
- 实现隔离网络间的通讯
需要在需要通信的一方加上对方的网卡即可,我们实验的几个容器如下所示:[vagrant@localhost ~]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f5b592f7b940 centos-ip-new "/bin/bash" 4 hours ago Up 4 hours quirky_roentgen 3aec978eea9b centos-ip-new "/bin/bash" 4 hours ago Up 4 hours blissful_raman 7044428bd01f centos-ip-new "/bin/bash" 4 hours ago Up 4 hours mystifying_swanson
其中,f5b592f7b940 是 172.17.0.1/16 网络的,其余两个是 172.20.16.1/16 网络的。
为 f5b592f7b940 容器添加 self_net 网卡:[vagrant@localhost ~]$ docker network connect self_net f5b592f7b940
登陆容器中查看网络配置情况
[root@f5b592f7b940 /]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe11:2/64 scope link valid_lft forever preferred_lft forever 14: eth1@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:14:00:01 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.20.0.1/16 scope global eth1 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe14:1/64 scope link valid_lft forever preferred_lft forever
容器中已经增加了一个网卡 eth1@if15
[root@f5b592f7b940 /]# ping -c 3 172.20.16.3 PING 172.20.16.3 (172.20.16.3) 56(84) bytes of data. 64 bytes from 172.20.16.3: icmp_seq=1 ttl=64 time=0.877 ms 64 bytes from 172.20.16.3: icmp_seq=2 ttl=64 time=0.061 ms ^C --- 172.20.16.3 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.061/0.469/0.877/0.408 ms
如上,通讯没有问题。
五、容器间的通信
前言,要想实现容器间进行通信,必须保证有属于同一个网络的网卡。这一点我们在前面就已经证明了。
- 通过 IP 通信
具体的做法有两种:1、在创建容器的时候通过 --network 指定相应的网络;2、在 host 上通过 docker network connect 将现有容器加入到指定的网络。 - Docker DNS Server
为了避免 IP 不灵活造成的麻烦,可以使用 Docker 自带的 Dns 服务。docker daemon 实现了一个内嵌的 DNS Server,是容器可以直接通过“容器名”通信。所以在启动容器的时候使用 --name 为容器命名即可。同时必须使用 user-defined 网络才可以。默认的 bridge 网络是不可以互相通信访问的。
创建两个容器 centos1 和 centos2
[vagrant@localhost ~]$ docker run -it --rm --network=self_net --name=centos1 centos-ip-new [vagrant@localhost ~]$ docker run -it --rm --network=self_net --name=centos2 centos-ip-new [vagrant@localhost ~]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES db798aad7dc2 centos-ip-new "/bin/bash" 6 seconds ago Up 5 seconds centos2 dc62fdb3dd0d centos-ip-new "/bin/bash" 13 minutes ago Up 13 minutes centos1
登陆 centos2 容器,直接 ping centos1
[root@db798aad7dc2 /]# ping -c 3 centos1 PING centos1 (172.20.0.1) 56(84) bytes of data. 64 bytes from centos1.self_net (172.20.0.1): icmp_seq=1 ttl=64 time=0.069 ms 64 bytes from centos1.self_net (172.20.0.1): icmp_seq=2 ttl=64 time=0.082 ms 64 bytes from centos1.self_net (172.20.0.1): icmp_seq=3 ttl=64 time=0.058 ms --- centos1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2001ms rtt min/avg/max/mdev = 0.058/0.069/0.082/0.013 ms
验证可以容器名称直接进行通信,Docker DNS Server起作用。
现在验证下直接使用默认的 Bridge 是否可以进行通信,创建容器 centos3、 centos4
[vagrant@localhost ~]$ docker run -it --rm --name=centos3 centos-ip-new [vagrant@localhost ~]$ docker run -it --rm --name=centos4 centos-ip-new [vagrant@localhost ~]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 69687166db7a centos-ip-new "/bin/bash" 4 seconds ago Up 3 seconds centos4 2bc8e5869465 centos-ip-new "/bin/bash" 9 seconds ago Up 9 seconds centos3
尝试着在 centos3上面进行 ping 操作
[root@2bc8e5869465 /]# ping -c 3 centos4 PING centos4.localdomain (42.123.125.237) 56(84) bytes of data. 64 bytes from 42.123.125.237 (42.123.125.237): icmp_seq=1 ttl=47 time=51.7 ms 64 bytes from 42.123.125.237 (42.123.125.237): icmp_seq=2 ttl=47 time=51.5 ms 64 bytes from 42.123.125.237 (42.123.125.237): icmp_seq=3 ttl=47 time=52.4 ms --- centos4.localdomain ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 3840ms rtt min/avg/max/mdev = 51.500/51.902/52.410/0.378 ms
以上,并没有出现书上说的 bad address 提示,而是连接到了远方了,^_^。
- joined 容器
joined 容器可以使两个或者多个容器共用一个网络栈,共享网卡和网络配置,容器之间可通过 127.0.0.1 直接进行通信,这个在高效通信的时候经常用到。
首先创建一个容器 centos5,并查看网络配置[vagrant@localhost ~]$ docker run -it --rm --name=centos5 centos-ip-new [root@417c71ddc5df /]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 33: eth0@if34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe11:2/64 scope link valid_lft forever preferred_lft forever
再创建一个容器 centos6 ,并通过 --network=container:<需要joined 到当前容器的 容器名称> 指定 joined 容器为 centos5,并查看网络配置
[vagrant@localhost ~]$ docker run -it --rm --network=container:centos5 --name=centos6 centos-ip-new [root@417c71ddc5df /]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 33: eth0@if34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe11:2/64 scope link valid_lft forever preferred_lft forever
可以看到,centos5 和 centos6 两个容器的网卡 mac 地址和 IP 完全一样,即共享了相同的网络栈。
当前仅仅对单宿主机的docker网络通信进行分析,后续我们将对多宿主机之间的docker通信进行分析讨论。