八、 Docker网络管理
八、 Docker网络管理

八、 Docker网络管理

8.1 Docker的默认的网络通信

8.1.1 Docker安装后默认的网络设置

Docker服务安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡,其ip地址都是172.17.0.1/16

root@ubuntu-2010:~# ip a
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:e0:e8:04:f5 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:e0ff:fee8:4f5/64 scope link 
       valid_lft forever preferred_lft forever
root@ubuntu-2010:~# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242e0e804f5	no		

8.1.2 创建容器后的网络配置

每次新建容器后

  • 宿主机多了一个虚拟网卡,和容器的网卡组合成一个网卡,比如: 137: veth8ca6d43@if136,而在容器内的网卡名为136,可以看出和宿主机的网卡之间的关联
  • 容器会自动获取一个172.17.0.0/16网段的随机地址,默认从172.17.0.2开始,第二次容器为172.17.0.3,以此类推
  • 容器获取的地址并不固定,每次容器重启,可能会发生地址变化

8.1.2.1 创建第一个容器后的网络状态

创建容器后,容器自动获取ip地址

root@ubuntu-2010:~# docker run -ti --rm alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
80: eth0@if81: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 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	11a5e589ef8a
# root@ubuntu-2010:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
11a5e589ef8a   alpine    "sh"      30 seconds ago   Up 29 seconds             trusting_swartz

新建第一个容器,宿主机的网卡状态

root@ubuntu-2010:~# ip a 
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:ee:4a:fa brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    altname ens33
    inet 10.0.0.210/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feee:4afa/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:e0:e8:04:f5 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:e0ff:fee8:4f5/64 scope link 
       valid_lft forever preferred_lft forever
81: veth9e40094@if80: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether f6:bf:36:e7:d4:17 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::f4bf:36ff:fee7:d417/64 scope link 
       valid_lft forever preferred_lft forever

查看新建容器后桥接状态

root@ubuntu-2010:~# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242e0e804f5	no		veth9e40094

8.1.2.1 创建第二个容器后的网络状态

再次创建第二个容器

root@ubuntu-2010:~# docker run -ti --rm alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
82: eth0@if83: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 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	d40a93c0f6c3
/ # ping f92aa8306175
PING f92aa8306175 (69.172.200.109): 56 data bytes
^C
--- f92aa8306175 ping statistics ---
7 packets transmitted, 0 packets received, 100% packet loss
/ # ping d40a93c0f6c3
PING d40a93c0f6c3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.027 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.046 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.065 ms

root@ubuntu-2010:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
d40a93c0f6c3   alpine    "sh"      2 minutes ago   Up 2 minutes             exciting_kirch
11a5e589ef8a   alpine    "sh"      7 minutes ago   Up 7 minutes             trusting_swartz

新建第二个容器后又多了一个虚拟网卡

root@ubuntu-2010:~# ip a 
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:ee:4a:fa brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    altname ens33
    inet 10.0.0.210/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feee:4afa/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:e0:e8:04:f5 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:e0ff:fee8:4f5/64 scope link 
       valid_lft forever preferred_lft forever
81: veth9e40094@if80: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether f6:bf:36:e7:d4:17 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::f4bf:36ff:fee7:d417/64 scope link 
       valid_lft forever preferred_lft forever
83: veth7da37ea@if82: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 46:4a:fd:66:a5:ed brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::444a:fdff:fe66:a5ed/64 scope link 
       valid_lft forever preferred_lft forever

查看新建第二个容器后桥接状态

root@ubuntu-2010:~# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242e0e804f5	no		veth7da37ea
							veth9e40094

8.1.3 容器间通信

8.1.3.1 同一个宿主机的不同容器可互相通信

默认情况下

  • 同一个宿主机的不同容器之间可以相互通信
dockerd --icc Enable inter-container communication (default true)
--icc=false 可以禁止通信
  • 不同宿主机之间的容器IP地址重复,不能相互通信

同一宿主机的容器之间访问

root@ubuntu-2010:~# docker run -ti alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
94: eth0@if95: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
# root@ubuntu-2010:~# docker run -ti --rm alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
96: eth0@if97: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1): 56 data bytes
64 bytes from 172.17.0.1: seq=0 ttl=64 time=0.156 ms
64 bytes from 172.17.0.1: seq=1 ttl=64 time=0.058 ms
^C
--- 172.17.0.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.058/0.107/0.156 ms
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.186 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.073 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.073/0.129/0.186 ms

8.1.3.2 禁止同一宿主机的不同容器间通信

范例:同一宿主机不同容器间禁止通信

#dockerd的--icc=false 选项可以禁止同一个宿主机的不同容器间通信
root@ubuntu-2010:~# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --icc=false
root@ubuntu-2010:~# systemctl daemon-reload 
root@ubuntu-2010:~# systemctl restart docker

#--icc选项本质是修改iptables规则,pre.filter是--icc=true,pre2.filter是--icc=false
root@ubuntu-2010:~# iptables -S > pre2.filter
root@ubuntu-2010:~# diff pre.filter pre2.filter 
13c13
< -A FORWARD -i docker0 -o docker0 -j ACCEPT
---
> -A FORWARD -i docker0 -o docker0 -j DROP

8.1.4 修改默认网络设置使用自定义网桥

新建容器默认使用docker0的网络配置,可以修改默认指向自定义的网桥网络

  • 用自定义的网桥替代默认的docker0
root@ubuntu-2010:~# ip a 
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:89:46:ef brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    altname ens33
    inet 10.0.0.200/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe89:46ef/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:60:77:12:9d brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

root@ubuntu-2010:~# apt -y install bridge-utils
root@ubuntu-2010:~# brctl addbr br0
root@ubuntu-2010:~# ip a a 192.168.100.1/24 dev br0
root@ubuntu-2010:~# brctl show
bridge name	bridge id		STP enabled	interfaces
br0		8000.000000000000	no		
docker0		8000.02426077129d	no		
root@ubuntu-2010:~# ip a 
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:89:46:ef brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    altname ens33
    inet 10.0.0.200/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe89:46ef/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:60:77:12:9d brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
4: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 1a:83:16:1d:43:89 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 scope global br0
       valid_lft forever preferred_lft forever

root@ubuntu-2010:~# vim /lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
-b br0
root@ubuntu-2010:~# systemctl daemon-reload 
root@ubuntu-2010:~# systemctl restart docker
root@ubuntu-2010:~# ps -ef | grep dockerd
root       97066       1  1 04:46 ?        00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -b br0
root       97196   93416  0 04:46 pts/0    00:00:00 grep --color=auto dockerd
root@ubuntu-2010:~# docker run --rm alpine hostname -i

192.168.100.2

8.2 容器名称互联

新建容器时,docker会给容器自动分配名称,容器ID和IP地址,导致容器名称,容器ID和IP不固定,那么如何区分不同的容器,实现和确定目标容器通信呢?解决方案是给容器起个固定的名称,容器之间通过固定名称实现确定目标的通信

有两种固定名称:

  • 容器名称
  • 容器名称的别名

注意:两种方式都是最少需要两个容器才能实现

8.2.1 通过容器名称互联

8.2.1.1 容器名称介绍

在同一宿主机上的容器之间可以通过自定义的容器名称相互访问,比如:一个业务前端静态页面是使用nginx,动态页面使用的是tomcat,另外还需要负载均衡调度器,如:haproxy对请求调度至nginx和tomcat容器,由于容器在启动的时候其内部IP地址是DHCP随机分配的,而给容器起个固定的名称,则是相对比较固定的,因此比较适用于此场景

注意:如果被引用的容器地址变化,必须重启当前容器才能生效

8.2.1.2 容器名称实现

docker run 创建容器,可使用–link选项实现容器名称的引用,其本质就是在容器内的/etc/hosts中添加–link后指定的容器的IP和主机名的对应关系,从而实现名称解析

--link list        Add link to another container
格式:
docker run --name <容器名称>                         #先创建指定名称的容器
docker run --link <目标通信的容器ID或容器名称>       #再创建容器时引用上面容器的名称

8.2.1.3 案例:使用容器名称进行容器间通信

  • 先创建第一个指定容器名称的容器
root@ubuntu-2010:~# docker run -ti --rm --name server1 alpine
/ # 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	de8bf4af716f
  • 新建第二个容器时引用第一个容器的名称

会自动将第一个主机的名称加入/etc/hosts文件,从而可以利用第一个容器名称进行访问

root@ubuntu-2010:~# docker run -ti --rm --name server2 --link server1 alpine
/ # env
HOSTNAME=555be633aa00
SHLVL=1
HOME=/root
SERVER1_NAME=/server2/server1
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
/ # 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	server1 de8bf4af716f
172.17.0.3	555be633aa00
/ # ping server1
PING server1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.131 ms

8.2.2 通过自定义容器别名互联

8.2.2.1 容器别名介绍

自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,容器内程序之间也必须要随之发生变化,比如:程序通过固定的容器名称进行服务调用,但是容器名称发生变化后再使用之前的名称肯定是无法成功调用,每次都进行更改的话又比较麻烦,因此可以使用自定义别名的方式解决,即容器名称可以随意更改,只要不更改别名即可

8.2.2.2 容器别名实现

命令格式:

docker run --name <容器名称>                                                      #先创建指定名称的容器
docker run --name <容器名称> --link <目标容器名称>:"<容器别名1> <容器别名2> ..."  #给上
面创建的容器起别名,来创建新容器

8.2.2.3 案例:使用容器别名

  • 创建第三个容器,引用前面的容器,并起多个别名
root@ubuntu-2010:~# docker run -ti --rm --name server3 --link server1:"server1-alias1 server1-alias2" --link server2:server2-alias alpine
/ # 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	server1-alias1 server1-alias2 de8bf4af716f server1
172.17.0.3	server2-alias 555be633aa00 server2
172.17.0.4	899144bbda6c

8.3 docker网络连接

8.3.1 docker网络模式介绍

Docker的网络支持5种网络模式

  • none
  • bridge
  • host
  • container
  • network-name

查看默认的网络模式有三个

root@ubuntu-2010:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
00b5433d68e7   bridge    bridge    local
784ef8827cf0   host      host      local
77884fabbcfa   none      null      local

8.3.2 网络模式指定

默认新建的容器使用Bridge模式,创建容器时,docker run 命令使用以下选项指定网络模式

格式:

docker run --network <mode>
docker run --net=<mode>

<mode>: 可是以下值
none
bridge
host
container:<容器名或容器ID>
<自定义网络名称>

8.3.3 bridge网络模式

8.3.3.1 bridge 网络模式架构

本模式是docker的默认模式,即不指定任何模式就是bridge模式,也是使用比较多的模式,此模式创建的容器会为每一个容器分配自己的网络IP等信息,并将容器连接到一个虚拟网桥与外界通信
可以和外部网络之间进行通信,通过SNAT访问外网,使用DNAT可以让容器被外部主机访问,所以此模式也称为NAT模式

此模式宿主机需要启动ip_forward功能

bridge网络模式特点

  • 网络资源隔离: 不同宿主机的容器无法直接通信,各自使用独立网络
  • 无需手动配置: 容器默认自动获取172.17.0.0/16的IP地址,此地址可以修改
  • 可访问外网: 利用宿主机的物理网卡,SNAT连接外网
  • 外部主机无法直接访问容器: 可以通过配置DNAT接受外网的访问
  • 低性能较低: 因为可通过NAT,网络转换带来更的损耗
  • 端口管理繁琐: 每个容器必须手动指定唯一的端口,容器产生端口冲突

8.3.3.2 bridge 模式的默认设置

  • 查看bridge模式信息
root@ubuntu-2010:~# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "00b5433d68e7d322876e91c65f81402d0a68bbf7d1f9795da727c1c894400432",
        "Created": "2021-09-21T04:48:57.827808699Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "555be633aa009dca31bc9004f96a011479ba5f9a5b4b104c8a6ec6abcc9cc525": {
                "Name": "server2",
                "EndpointID": "40403adee3ac783358294829677b32cfff41ae548e6a43ca93c50c67583de604",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "899144bbda6cd47053a0315db72f1112238962db521a3820e0d1c1547ec00bf3": {
                "Name": "server3",
                "EndpointID": "d472f228d0a1b5bac65697407b3126f6c84f015881c02765eef6bf9cc2365355",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            },
            "de8bf4af716fa4c64fb9a7c3a4a962accc23f3dd62be73e4e510a8205663e254": {
                "Name": "server1",
                "EndpointID": "6dbdb2af8fe2c5c00666b846a1d42767af52c7272d136bc06e933227b193fa61",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
  • 宿主机的网络状态
root@ubuntu-2010:~# cat /proc/sys/net/ipv4/ip_forward
1
root@ubuntu-2010:~# iptables -S -t nat
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P POSTROUTING ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A DOCKER -i docker0 -j RETURN
root@ubuntu-2010:~# iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0
  • 通过宿主机的物理网卡利用SNAT访问外部网络
#在另一台主机上建立httpd服务器
[root@centos7 ~]# echo `hostname -I` > /var/www/html/index.html
[root@centos7 ~]# curl localhost
10.0.0.7
[root@centos7 ~]# systemctl is-active httpd
active

#启动容器,默认是bridge网络模式
root@ubuntu-2010:~# docker run -ti --rm alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
106: eth0@if107: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 10.0.0.7
PING 10.0.0.7 (10.0.0.7): 56 data bytes
64 bytes from 10.0.0.7: seq=0 ttl=63 time=1.006 ms
64 bytes from 10.0.0.7: seq=1 ttl=63 time=0.829 ms
^C
--- 10.0.0.7 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.829/0.917/1.006 ms
/ # ping -c 1 www.baidu.com
PING www.baidu.com (14.215.177.39): 56 data bytes
64 bytes from 14.215.177.39: seq=0 ttl=127 time=7.417 ms

--- www.baidu.com ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 7.417/7.417/7.417 ms
/ # wget -qO - 10.0.0.7
10.0.0.7

[root@centos7 ~]# tail /var/log/httpd/access_log 
10.0.0.210 - - [21/Sep/2021:21:59:40 +0800] "GET / HTTP/1.1" 200 9 "-" "Wget"

8.3.3.3 修改默认的bridge模式网络配置

有两种方法修改默认的bridge模式的网络配置,但两种方式只能选一种,否则会导致冲突,docker服务无法启动

  • 修改/lib/systemd/system/docker.service,此方法以在之前做过介绍
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
 --bip=10.100.0.1/24
  • 修改/etc/docker/daemon.json
root@ubuntu-2010:~# vim /etc/docker/daemon.json 

{
  "registry-mirrors":["https://hub-mirror.c.163.com"],
  "bip": "172.30.0.1/24"
}
root@ubuntu-2010:~# systemctl daemon-reload 
root@ubuntu-2010:~# systemctl restart docker
root@ubuntu-2010:~# ip a
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:89:46:ef brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    altname ens33
    inet 10.0.0.200/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe89:46ef/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:60:77:12:9d brd ff:ff:ff:ff:ff:ff
    inet 172.30.0.1/24 brd 172.30.0.255 scope global docker0
       valid_lft forever preferred_lft forever
root@ubuntu-2010:~# docker network inspect bridge 
[
    {
        "Name": "bridge",
        "Id": "a81034a5226ad868e70a5a05cc80f57f141f8518af78a11bba63a450ca88b8d3",
        "Created": "2021-09-21T14:05:32.805271015Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.30.0.0/24",
                    "Gateway": "172.30.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

8.3.4 Host模式

如果指定host模式启动的容器,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址,因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口即可,不过容器内除网络以外的其他资源,如:文件系统、系统进程等仍然和宿主机保持隔离

此模式由于直接使用宿主机的网络无需转换,网络性能最高,但是各容器内使用的端口不能相同,适用于运行容器端口比较固定的业务

Host网络模式特点:

  • 使用参数 –network host 指定
  • 共享宿主机网络
  • 网络性能无损耗
  • 网络故障排除相对简单
  • 各容器网络无隔离
  • 网络资源无法分别统计
  • 端口管理困难:容易产生端口冲突
  • 不支持端口映射
#确认宿主机网络设置
root@ubuntu-2010:~# 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:e0ff:fee8:4f5  prefixlen 64  scopeid 0x20<link>
        ether 02:42:e0:e8:04:f5  txqueuelen 0  (Ethernet)
        RX packets 674  bytes 40278 (40.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 774  bytes 4319229 (4.3 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.210  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:feee:4afa  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:ee:4a:fa  txqueuelen 1000  (Ethernet)
        RX packets 426075  bytes 338021839 (338.0 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 45795  bytes 3950660 (3.9 MB)
        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 800  bytes 72950 (72.9 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 800  bytes 72950 (72.9 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

root@ubuntu-2010:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.1        0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

#启动容器前确认是否有启用80端口
root@ubuntu-2010:~# lsof -i:80


#创建host模式的容器
root@ubuntu-2010:~# docker run -d --network host --name web1 httpd
24c8b8645449e70ccbad8a5f040e2a76a14809ee6edda117ea7d15c3a0f00498


#创建容器后,宿主机的80/tcp端口打开
root@ubuntu-2010:~# lsof -i:80
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
httpd   89788   root    4u  IPv6 398309      0t0  TCP *:http (LISTEN)
httpd   89807 daemon    4u  IPv6 398309      0t0  TCP *:http (LISTEN)
httpd   89808 daemon    4u  IPv6 398309      0t0  TCP *:http (LISTEN)
httpd   89809 daemon    4u  IPv6 398309      0t0  TCP *:http (LISTEN)

#进入容器
root@ubuntu-2010:~# docker exec -ti web1 bash
root@ubuntu-2010:/# apt update
root@ubuntu-2010:/# apt -y install net-tools
root@ubuntu-2010:/# 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:e0ff:fee8:4f5  prefixlen 64  scopeid 0x20<link>
        ether 02:42:e0:e8:04:f5  txqueuelen 0  (Ethernet)
        RX packets 674  bytes 40278 (39.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 774  bytes 4319229 (4.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.210  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:feee:4afa  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:ee:4a:fa  txqueuelen 1000  (Ethernet)
        RX packets 454240  bytes 375942865 (358.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 49764  bytes 4294600 (4.0 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 872  bytes 79454 (77.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 872  bytes 79454 (77.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

root@ubuntu-2010:/# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.1        0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

root@ubuntu-2010:/# echo "Test Page in app" > usr/share/nginx/html/index.html

#从容器访问远程主机
root@ubuntu-2010:/# curl 10.0.0.7
10.0.0.7

#查看远程主机的访问日志
[root@centos7 ~]# tail /var/log/httpd/access_log
10.0.0.210 - - [21/Sep/2021:22:24:51 +0800] "GET / HTTP/1.1" 200 9 "-" "curl/7.64.0"

#远程主机可以访问容器的web服务
[root@centos7 ~]# curl 10.0.0.210
Test Page in app

8.3.5 none 模式

在使用none模式后,Docker容器不会进行任何网络配置,没有网卡、没有IP,也没有路由,因此默认无法与外界通信,需要手动添加网卡配置IP等,所以极少使用

none 模式特点:

  • 使用参数 –network none 指定
  • 默认无网络功能,无法和外部通信

启动一个none模式的容器

root@ubuntu-2010:~# docker run -ti --network none -p 80:80 --name web1-none alpine
/ # 
/ # ifconfig -a
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

/ # ping -c 1 baidu.com
ping: bad address 'baidu.com'
/ # ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1): 56 data bytes
ping: sendto: Network unreachable

8.3.6 Container 模式

使用此模式创建的容器需要指定一个已经存在的容器共享一个网络,而不是和宿主机共享网络,新创建的容器不会创建自己的网卡也不会配置自己的IP,而是和一个被指定的已经存在的容器共享IP和端口范围,因此这个容器的端口不能和被指定容器的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离,两个容器的进程可以通过lo网卡进行通信

Container模式特点:

  • 使用参数 –-network container:名称或ID 指定
  • 与宿主机网络空间隔离
  • 空器间共享网络空间
  • 适合频繁的容器间的网络通信
  • 直接使用对方的网络,较少使用
root@ubuntu-2010:~# docker run -ti --name server1 -p 80:80 alpine sh
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:736 (736.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State


root@ubuntu-2010:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS                               NAMES
d87febb07525   alpine    "sh"      2 minutes ago   Up 2 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   server1
root@ubuntu-2010:~# docker port server1
80/tcp -> 0.0.0.0:80
80/tcp -> :::80
root@ubuntu-2010:~# curl localhost
curl: (56) Recv failure: Connection reset by peer

#创建第二个容器,基于第一个容器的container的网络模式
root@ubuntu-2010:~# docker run -d --name server2 --network container:server1 nginx

#可以访问web服务
root@ubuntu-2010:~# curl localhost
Welcome to nginx!

root@d87febb07525:/# 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 1568  bytes 9748112 (9.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1419  bytes 85349 (83.3 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
        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@d87febb07525:/# netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     
tcp6       0      0 :::80                   :::*                    LISTEN

#可以访问外网
root@d87febb07525:/# curl -I baidu.com
HTTP/1.1 200 OK
Date: Tue, 21 Sep 2021 14:59:07 GMT
Server: Apache
Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
ETag: "51-47cf7e6ee8400"
Accept-Ranges: bytes
Content-Length: 81
Cache-Control: max-age=86400
Expires: Wed, 22 Sep 2021 14:59:07 GMT
Connection: Keep-Alive
Content-Type: text/html

8.3.7 自定义网络模式

除了以上的网络模式,也可以自定义网络,使用自定义的网段地址,网关等信息

注意:自定义网络可以直接通过容器名进行相互的访问,而无需使用–link

可以使用自定义网络模式,实现不同集群应用的独立网络管理,而互不影响,而且在同一个网络内,可以直接利用容器名相互访问,非常便利

8.3.7.1 自定义网络实现

[root@ubuntu1804 ~]#docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect             Connect a container to a network
create              Create a network
disconnect          Disconnect a container from a network
inspect             Display detailed information on one or more networks
ls                  List networks
prune               Remove all unused networks
rm                  Remove one or more networks

创建自定义网络:

docker network create -d <mode> --subnet <CIDR> --gateway <网关> <自定义网络名称>
#注意mode不支持host和none,默认是bridge模式

查看自定义网络信息

docker network inspect <自定义网络名称或网络ID>

引用自定义网络

docker run --network <自定义网络名称> <镜像名称>

删除自定义网络

doccker network rm <自定义网络名称或网络ID>

内置的三个网络无法删除

root@ubuntu-2010:~# docker network rm none
Error response from daemon: none is a pre-defined network and cannot be removed
root@ubuntu-2010:~# docker network rm host
Error response from daemon: host is a pre-defined network and cannot be removed
root@ubuntu-2010:~# docker network rm bridge
Error response from daemon: bridge is a pre-defined network and cannot be removed

8.3.7.2 自定义网络案例

root@ubuntu-2010:~# docker network create -d bridge --subnet 172.27.0.0/24 --gateway 172.27.0.1 test-net
58c792ac9e6cc680e3d60bb45e84149aa21f8f5c4cc315be44c8b2bb5aad9a6f
root@ubuntu-2010:~# docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
00b5433d68e7   bridge     bridge    local
784ef8827cf0   host       host      local
77884fabbcfa   none       null      local
58c792ac9e6c   test-net   bridge    local
root@ubuntu-2010:~# docker inspect test-net 
[
    {
        "Name": "test-net",
        "Id": "58c792ac9e6cc680e3d60bb45e84149aa21f8f5c4cc315be44c8b2bb5aad9a6f",
        "Created": "2021-09-21T15:06:19.430890453Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.27.0.0/24",
                    "Gateway": "172.27.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

root@ubuntu-2010:~# ip a 
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:ee:4a:fa brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    altname ens33
    inet 10.0.0.210/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feee:4afa/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:e0:e8:04:f5 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:e0ff:fee8:4f5/64 scope link 
       valid_lft forever preferred_lft forever

#添加了一个虚拟网卡
110: br-58c792ac9e6c: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:8b:f7:8e:09 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.1/24 brd 172.27.0.255 scope global br-58c792ac9e6c
       valid_lft forever preferred_lft forever

#新增一个网桥
root@ubuntu-2010:~# brctl show
bridge name	bridge id		STP enabled	interfaces
br-58c792ac9e6c		8000.02428bf78e09	no		
docker0		8000.0242e0e804f5	no

root@ubuntu-2010:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.1        0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.27.0.0      0.0.0.0         255.255.255.0   U     0      0        0 br-58c792ac9e6c

root@ubuntu-2010:~# docker run -ti --rm --network test-net alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
111: eth0@if112: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/24 brd 172.27.0.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.27.0.1      0.0.0.0         UG    0      0        0 eth0
172.27.0.0      0.0.0.0         255.255.255.0   U     0      0        0 eth0
/ # cat /etc/resolv.conf 
search test.com test.org
nameserver 127.0.0.11
options edns0 trust-ad ndots:0
/ # ping -c1 baidu.com
PING baidu.com (220.181.38.251): 56 data bytes
64 bytes from 220.181.38.251: seq=0 ttl=127 time=42.409 ms

--- baidu.com ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 42.409/42.409/42.409 ms

#再次检查网络信息,会出现此网络中容器的网络信息
root@ubuntu-2010:~# docker network inspect test-net 
[
    {
        "Name": "test-net",
        "Id": "58c792ac9e6cc680e3d60bb45e84149aa21f8f5c4cc315be44c8b2bb5aad9a6f",
        "Created": "2021-09-21T15:06:19.430890453Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.27.0.0/24",
                    "Gateway": "172.27.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "b2cfd15944c41c90c0d730d5bc6f58525514da7996243485d63fe011b3492f11": {
                "Name": "keen_napier",
                "EndpointID": "62c6a487c8efbd287538ef3c4e866564b6b39f0bf08382045fbbe1b7c1e6b48a",
                "MacAddress": "02:42:ac:1b:00:02",
                "IPv4Address": "172.27.0.2/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

8.3.7.3 自定义网络中的容器之间通信案例

root@ubuntu-2010:~# docker run -ti --rm --network test-net --name test1 alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
113: eth0@if114: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/24 brd 172.27.0.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 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.27.0.2	5233b632f2c5

root@ubuntu-2010:~# docker run -ti --rm --network test-net --name test2 alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
115: eth0@if116: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:1b:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.3/24 brd 172.27.0.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 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.27.0.3	60cd2e5d9c1e
/ # ping -c1 test1
PING test1 (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0 ttl=64 time=0.160 ms

--- test1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.160/0.160/0.160 ms

结论:自定义网络中的容器之间可以直接利用容器名进行通信

8.3.8 同一个宿主机之间不同网络的容器通信

开两个容器,一个使用自定义网络容器,一个使用默认bridge网络的容器,默认无法通信,利用单臂路由实现通信

root@ubuntu-2010:~# docker run -ti --rm --name test1 alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
117: eth0@if118: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

root@ubuntu-2010:~# docker run -ti --rm --network test-net --name test2 alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
119: eth0@if120: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/24 brd 172.27.0.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping -c1 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes

--- 172.17.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss

8.3.8.1 自定义网络和bridge网络容器之间无法通信的原因

root@ubuntu-2010:~# cat /proc/sys/net/ipv4/ip_forward
1
root@ubuntu-2010:~# brctl show
bridge name	bridge id		STP enabled	interfaces
br-58c792ac9e6c		8000.02428bf78e09	no		
docker0		8000.0242e0e804f5	no		
root@ubuntu-2010:~# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   13  1069 DOCKER-USER  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
   13  1069 DOCKER-ISOLATION-STAGE-1  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    6   605 ACCEPT     all  --  *      br-58c792ac9e6c  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    1    84 DOCKER     all  --  *      br-58c792ac9e6c  0.0.0.0/0            0.0.0.0/0           
    5   296 ACCEPT     all  --  br-58c792ac9e6c !br-58c792ac9e6c  0.0.0.0/0            0.0.0.0/0           
    1    84 ACCEPT     all  --  br-58c792ac9e6c br-58c792ac9e6c  0.0.0.0/0            0.0.0.0/0           
 3447   27M ACCEPT     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    1    84 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0           
 2853  132K ACCEPT     all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0           
    1    84 ACCEPT     all  --  docker0 docker0  0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    6   380 DOCKER-ISOLATION-STAGE-2  all  --  br-58c792ac9e6c !br-58c792ac9e6c  0.0.0.0/0            0.0.0.0/0           
 2853  132K DOCKER-ISOLATION-STAGE-2  all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0           
 6313   27M RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain DOCKER-USER (1 references)
 pkts bytes target     prot opt in     out     source               destination         
 7350   32M RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  *      br-58c792ac9e6c  0.0.0.0/0            0.0.0.0/0           
    1    84 DROP       all  --  *      docker0  0.0.0.0/0            0.0.0.0/0           
 2858  132K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0

root@ubuntu-2010:~# iptables -I DOCKER-ISOLATION-STAGE-2 -j ACCEPT
root@ubuntu-2010:~# docker exec -ti test1 sh
/ # ping 172.27.0.2
PING 172.27.0.2 (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0 ttl=63 time=0.116 ms

root@ubuntu-2010:~# docker exec -ti test2 sh
/ # ping -c1 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=63 time=0.089 ms

8.3.8.2 解决同一宿主机不同网络的容器间无法通信的问题

可以使用docker network connect命令实现同一个宿主机不同网络的容器间相互通信

#将CONTAINER连入指定的NETWORK中,使此CONTAINER可以与CONTAINER中的其它容器进行通信
docker network connect [OPTIONS] NETWORK CONTAINER

Connect a container to a network
Options:
--alias strings                  Add network-scoped alias for the container
--driver-opt strings             driver options for the network
--ip string                      IPv4 address (e.g., 172.30.100.104)
--ip6 string                     IPv6 address (e.g., 2001:db8::33)
--link list                      Add link to another container
--link-local-ip strings          Add a link-local address for the container

#将CONTAINER与指定的NETWORK断开连接,使此CONTAINER可以与CONTAINER中的其它容器进行无法通信
#如果将容器从自定义的网络删除,将加入默认的网络,即docker0网桥中,获取172.17.0.0/16
#如果将容器从默认的网络docker0删除,将加入none网络
docker network disconnect [OPTIONS] NETWORK CONTAINER
Disconnect a container from a network
Options:
-f, --force         Force the container to disconnect from a network
  • test1和test2的容器默认无法通信
#每个网络中有属于此网络的容器信息
root@ubuntu-2010:~# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "0de69e06e3516476a8b6b83fe6a29ef97acb0d741a8d577a6d622fe19a9ce954",
        "Created": "2021-09-21T15:36:19.025464664Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "5c1a35deafba77fc0811cee5135562f80eb09e76176468f4d5f112edb294ef5d": {
                "Name": "test1",
                "EndpointID": "bf3ee6efb34fc96491e5473ed143b7de3f9c1ad3ae5c9afb5eab2edfac49079f",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

root@ubuntu-2010:~# docker network inspect test-net 
[
    {
        "Name": "test-net",
        "Id": "58c792ac9e6cc680e3d60bb45e84149aa21f8f5c4cc315be44c8b2bb5aad9a6f",
        "Created": "2021-09-21T15:06:19.430890453Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.27.0.0/24",
                    "Gateway": "172.27.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "ec982db2a60b742c9859084a7809b290df472102db00879f5ae0124b6421ac4a": {
                "Name": "test2",
                "EndpointID": "4e7d2eb2633ade85bfd693f0b418a3a3ccdffdf6ca11c5576926008905f3d06f",
                "MacAddress": "02:42:ac:1b:00:02",
                "IPv4Address": "172.27.0.2/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
  • 让默认网络中容器test1可以连通自定义网络的容器test2
root@ubuntu-2010:~# docker network connect test-net test1
root@ubuntu-2010:~# docker network inspect test-net 
[
    {
        "Name": "test-net",
        "Id": "58c792ac9e6cc680e3d60bb45e84149aa21f8f5c4cc315be44c8b2bb5aad9a6f",
        "Created": "2021-09-21T15:06:19.430890453Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.27.0.0/24",
                    "Gateway": "172.27.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "5c1a35deafba77fc0811cee5135562f80eb09e76176468f4d5f112edb294ef5d": {
                "Name": "test1",
                "EndpointID": "c42bf659c8beacb4ff85da50aaa4a9bdfac4f573343affb6f3d165dcdb2fe2c6",
                "MacAddress": "02:42:ac:1b:00:03",
                "IPv4Address": "172.27.0.3/24",
                "IPv6Address": ""
            },
            "ec982db2a60b742c9859084a7809b290df472102db00879f5ae0124b6421ac4a": {
                "Name": "test2",
                "EndpointID": "4e7d2eb2633ade85bfd693f0b418a3a3ccdffdf6ca11c5576926008905f3d06f",
                "MacAddress": "02:42:ac:1b:00:02",
                "IPv4Address": "172.27.0.2/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

#在test1容器中可以看到新添加了一个网卡,并且分配了test-net网络的IP信息
root@ubuntu-2010:~# docker exec -ti test1 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
9: eth1@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:1b:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.3/24 brd 172.27.0.255 scope global eth1
       valid_lft forever preferred_lft forever
/ # ping -c1 172.27.0.2
PING 172.27.0.2 (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0 ttl=64 time=0.104 ms

--- 172.27.0.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.104/0.104/0.104 ms

#在test2容器中没有变化,仍然无法连接test1
root@ubuntu-2010:~# docker exec -ti test2 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
7: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/24 brd 172.27.0.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping -c1 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes

--- 172.17.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
  • 让自定义网络中容器test2可以连通默认网络的容器test1
#将自定义网络中的容器test2也加入到默认网络中,使之和默认网络中的容器test1通信
root@ubuntu-2010:~# docker network connect bridge test2
root@ubuntu-2010:~# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "0de69e06e3516476a8b6b83fe6a29ef97acb0d741a8d577a6d622fe19a9ce954",
        "Created": "2021-09-21T15:36:19.025464664Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "5c1a35deafba77fc0811cee5135562f80eb09e76176468f4d5f112edb294ef5d": {
                "Name": "test1",
                "EndpointID": "bf3ee6efb34fc96491e5473ed143b7de3f9c1ad3ae5c9afb5eab2edfac49079f",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "ec982db2a60b742c9859084a7809b290df472102db00879f5ae0124b6421ac4a": {
                "Name": "test2",
                "EndpointID": "3f86e8375c6c23f220b9982a813a7747251db6b77b2ac05cb9f0b34890b63077",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

#确认自定义网络的容器test2中添加了新网卡,并设置默认网络的IP信息
root@ubuntu-2010:~# docker exec -ti test2 sh
/ # ip a 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
7: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/24 brd 172.27.0.255 scope global eth0
       valid_lft forever preferred_lft forever
11: eth1@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth1
       valid_lft forever preferred_lft forever
/ # ping -c1 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.099 ms

--- 172.17.0.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.099/0.099/0.099 ms

#在test2中可以利用test1容器名通信
/ # ping -c1 test1
PING test1 (172.27.0.3): 56 data bytes
64 bytes from 172.27.0.3: seq=0 ttl=64 time=0.071 ms

--- test1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.071/0.071/0.071 ms

#在test1中可以利用test2容器名通信
/ # ping -c1 test2
PING test2 (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0 ttl=64 time=0.048 ms

--- test2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.048/0.048/0.048 ms
  • 断开不同网络中的网络通信
#将test1 断开和网络test-net中其它容器的通信
root@ubuntu-2010:~# docker network disconnect test-net test1
root@ubuntu-2010:~# docker exec -ti test1 sh
/ # ping 172.27.0.2
PING 172.27.0.2 (172.27.0.2): 56 data bytes

8.4 实现跨宿主机的容器之间网络互联

同一个宿主机之间的各容器之间是可以直接通信的,但是如果访问到另一台宿主机的容器呢?

8.4.1 docker跨主机互联实现说明

跨主机互联是说A宿主机的容器可以访问B主机上的容器,但是前提是保证各宿主机之间的网络是可以相互通信的,然后各容器才可以通过宿主机访问到对方的容器

实现原理:是在宿主机做一个网络路由就可以实现A宿主机的容器访问B主机的容器的目的

注意:此方式只适合小型网络环境,复杂的网络或者大型的网络可以使用google开源的k8s进行互联

8.4.2 修改各宿主机网段

Docker默认网段是172.17.0.x/16,而且每个宿主机都是一样的,因此要做路由的前提是各个主机的网络不能一致

8.4.2.1 第一个宿主机A上更改网段

root@ubuntu-2010:~# cat /etc/docker/daemon.json 
{
  "registry-mirrors":["https://hub-mirror.c.163.com"],
  "bip": "192.168.100.1/24"
}
root@ubuntu-2010:~# systemctl daemon-reload 
root@ubuntu-2010:~# systemctl restart docker
root@ubuntu-2010:~# ip a
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:6e:d1:fa brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    altname ens33
    inet 10.0.0.200/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe6e:d1fa/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:4a:91:5c:b6 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 brd 192.168.100.255 scope global docker0
       valid_lft forever preferred_lft forever

root@ubuntu-2010:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.1        0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 docker0

8.4.2.2 第二个宿主机B更改网段

[root@centos8-1 ~]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://3mihk855.mirror.aliyuncs.com"],
  "bip": "192.168.200.1/24"
}
[root@centos8-1 ~]# systemctl daemon-reload 
[root@centos8-1 ~]# systemctl restart docker
[root@centos8-1 ~]# ip a
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:3a:74:14 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.8/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a380:5e8b:aac8:5a0c/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:2f:d5:74:88 brd ff:ff:ff:ff:ff:ff
    inet 192.168.200.1/24 brd 192.168.100.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:2fff:fed5:7488/64 scope link 
       valid_lft forever preferred_lft forever

[root@centos8-1 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.1        0.0.0.0         UG    100    0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 eth0
192.168.200.0   0.0.0.0         255.255.255.0   U     0      0        0 docker0

8.4.3 在两个宿主机分别启动一个容器

第一个宿主机启动容器server1

root@ubuntu-2010:~# docker run -ti --rm --name server1 alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:c0:a8:64:02 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.2/24 brd 192.168.100.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.1   0.0.0.0         UG    0      0        0 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0

第二个宿主机启动容器server2

[root@centos8-1 ~]# docker run -ti --rm --name server2 alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:c0:a8:64:02 brd ff:ff:ff:ff:ff:ff
    inet 192.168.200.2/24 brd 192.168.100.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.200.1   0.0.0.0         UG    0      0        0 eth0
192.168.200.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0

从第一个宿主机的容器server1无法与第二个宿主机的server2互相访问

/ # ping -c1 192.168.100.2
PING 192.168.100.2 (192.168.100.2): 56 data bytes

--- 192.168.100.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss

/ # ping -c1 192.168.200.2
PING 192.168.200.2 (192.168.200.2): 56 data bytes

--- 192.168.200.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss

8.4.4 添加静态路由和iptables规则

在各宿主机添加静态路由,网关指向对方宿主机IP

8.4.4.1 在第一台宿主机添加静态路由和iptables规则

#添加路由
root@ubuntu-2010:~# route add -net 192.168.200.0/24 gw 10.0.0.8

#修改FORWARD默认规则
root@ubuntu-2010:~# iptables -P FORWARD ACCEPT
#或者修改iptables规则
root@ubuntu-2010:~# iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT

8.4.4.2 在第二台宿主机添加静态路由和iptables规则

#添加路由
[root@centos8-1 ~]# route add -net 192.168.100.0/24 gw 10.0.0.200
#修改FORWARD默认规则
[root@centos8-1 ~]# iptables -P FORWARD ACCEPT
#或者修改iptables规则
[root@centos8-1 ~]# iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT

8.4.5 测试跨宿主机之间容器互联

宿主机A的容器server1访问宿主机B容器server2,同时在宿主机B上tcpdump抓包观察

/ # ping -c1 192.168.200.2
PING 192.168.200.2 (192.168.200.2): 56 data bytes
64 bytes from 192.168.200.2: seq=0 ttl=62 time=0.987 ms

--- 192.168.200.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.987/0.987/0.987 ms

[root@centos8-1 ~]# tcpdump -i eth0 -nn icmp
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:18:01.118004 IP 10.0.0.200 > 192.168.200.2: ICMP echo request, id 8, seq 0, length 64
16:18:01.118139 IP 192.168.200.2 > 10.0.0.200: ICMP echo reply, id 8, seq 0, length 64

宿主机B的容器server2访问宿主机A的容器server1,同时在宿主机A上tcpdump抓包观察

/ # ping -c1 192.168.100.2
PING 192.168.100.2 (192.168.100.2): 56 data bytes
64 bytes from 192.168.100.2: seq=0 ttl=62 time=1.192 ms

--- 192.168.100.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 1.192/1.192/1.192 ms

root@ubuntu-2010:~# tcpdump -i eth0 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
08:19:17.244883 IP 10.0.0.8 > 192.168.100.2: ICMP echo request, id 8, seq 0, length 64
08:19:17.245031 IP 192.168.100.2 > 10.0.0.8: ICMP echo reply, id 8, seq 0, length 64

8.4.6 创建第三个容器测试

#在第二个宿主机B上启动第一个提供web服务的nginx容器server3
#注意无需打开端口映射
[root@centos8-1 ~]# docker run -d --name server3 nginx
[root@centos8-1 ~]# docker exec -ti server3 bash
root@e55a9e37da67:/# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.200.3  netmask 255.255.255.0  broadcast 192.168.200.255
        ether 02:42:c0:a8:c8:03  txqueuelen 0  (Ethernet)
        RX packets 4257  bytes 9328282 (8.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2599  bytes 143839 (140.4 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
        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

#从server1中访问server3的页面可以成功
/ # wget -qO - 192.168.200.3
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

#从server3容器观察访问日志,可以看到来自第一个宿主机,而非server1容器
[root@centos8-1 ~]# docker logs --tail 3 -f server3
2021/09/22 08:22:28 [alert] 1#1: unknown process 286 exited on signal 2
10.0.0.200 - - [22/Sep/2021:08:25:36 +0000] "GET / HTTP/1.1" 200 615 "-" "Wget" "-"
10.0.0.200 - - [22/Sep/2021:08:27:21 +0000] "GET / HTTP/1.1" 200 615 "-" "Wget" "-"

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注