Docker 网络之bridge模式
更新:HHH   时间:2023-1-7


本篇将讲述Docker网络的一些概念,以便您在设计和部署应用程序时充分利用到这些功能。

首先,Docker的网络子系统是可插拔驱动式的,默认情况下存在或支持多种网络接口,如bridge、host、overlay、macvlan以及none类型的网络接口。

接下来,我们先来探讨下bridge(桥接)网络模式

bridge是docker默认的网络模式,如果不指定类型,则这是您正在创建的网络类型,bridge模式会为每一个容器分配一个Network Namespace、IP等,并将容器的网络连接到一个网桥(docker0)上。

特点:同一个宿主机上所有容器默认会在同一个网段(默认网段:172.17.0.0/16)下,且相互之间可以通信以及访问外部网络(前提是宿主机可以访问外部网络)。

网桥就是在多个网段之间转发流量的链路层设备。网桥可以是运行在主机内核中的软件或者硬件设备。

Docker使用的是软件网桥,允许连接在同一网桥的容器间进行通信,同时提供与未连接到网桥网络的容器进行隔离。Docker网桥会自动设置相关规则(用iptables),不同网桥上的容器不能直接相互通信。

网桥适用于在同一个Docker守护程下的容器。对于在不同Docker守护进程下运行的容器之间的通信,可以在宿主机上添加路由,也可以使用overlay网络。

当启动Docker daemon时,会自动创建默认的网桥网络(docker0)并且还会启动iptables来设置您的访问规则。您可以创建用户自定义的网桥网络,用户自定义的网桥网络优于默认的网桥(docker0),特点如下:

1、用户自定义的网桥在容器化应用程序之间提供了更好的隔离性和互操作性。

连接在同一网桥下的容器同属一个网络,因此所有端口可以互访,但对外部网络是不公开的,这使得容器化应用程序可以轻松地相互通信,同时提高了安全性。

想象一下,一个带有web前端和后端,另外还有数据库的应用架构(用户<-->web入口<-->后端应用<-->数据库)。外部网络只需要访问web前端(如80端口),但只有后端应用需要访问数据库。若使用用户自定义的网桥,只需要对外开放web端口,数据库不需要对外开放任何端口,前后端都可以通过用户自定义的网桥来访问数据库。

2、用户自定义的网桥提供了容器之间的自动DNS解析。

在默认网桥上创建的容器,相互访问时只能通过IP地址,除非您使用--link选项,但--link是需要在容器的两个方向上创建,对于需要通信的两个以上的容器,这会变得复杂。而在用户自定义的网桥网络上,容器间可以通过名称或别名相互解析。

回想一下,在使用物理主机或者VM主机时,我们应用程序的配置文件中一般用hosts中的主机名称或者IP,而现在在容器中,使用自定义网络,我们只要改写成容器名就好了,不需要太关注主机名称或者IP,是不是很开森。

3、使用用户自定义网桥的容器,支持随时断开或连接到不同的(用户自定义)网络。

在容器的生命周期中,您可以动态切换容器间的网络连接,比如,您创建了自定义my-net01和my-net02桥接网络,这两个网络中的容器可以互相动态切换的。如果您是通过默认网桥创建的容器,也可以切换到自定义网桥中,而不必删除容器重建。

注:这里在实际验证过程中,貌似与官方文档描述有出入。

4、每个用户自定义的网络都是创建了一个可配置的网桥。

如果所有容器都使用默认网桥网络,虽说可以修改配置,但所有容器都使用相同的设置,例如MTU和iptables规则。此外,配置默认网桥网络需要重启Docker进程。

若是使用docker network create创建和配置用户自定义的网桥网络。如果不同的应用程序组有不同的网络需求,则可以在创建每个用户定义的网桥时分别对其进行配置。

5、使用默认网桥的容器之间可共享环境变量。

起初,在两个容器之间共享环境变量的唯一方法是使用--link。这种类型的变量共享在用户自定义的网络中是不可能的。然而,现在却有更好的方法来共享环境变量。

(1)、多个容器可以使用Docker的卷(Volume)来装载包含共享信息的文件或目录。

(2)、多个容器可以使用docker compose来一起启动,compose文件中可以定义共享变量。

(3)、可以使用swarm服务来代替独立的容器,并共享密钥和配置。

管理自定义网桥网络

1、使用docker network ls 查看默认支持网络

# docker network ls

NETWORK ID NAME DRIVER SCOPE

e22a6ab223fe bridge bridge local

15b417347346 host host local

5926c0bd11d0 none null local

2、使用docker network create 创建自定义网桥网络

# docker network create my-web-net01

# docker network ls

NETWORK ID NAME DRIVER SCOPE

e22a6ab223fe bridge bridge local

15b417347346 host host local

899362727b48 my-web-net01 bridge local

5926c0bd11d0 none null local

可以看到,我们并没有指定--driver=bridge来创建,因为默认就是bridge模式,当然,您也可以指定自定义网桥的子网、IP范围、网关和其他项,例如:

# docker network create --driver=bridge --subnet=172.23.10.0/24 my-web-net02

或者再细化一点

# docker network create \

--driver=bridge \

--subnet=172.24.0.0/16 \

--ip-range=172.24.10.0/24 \

--gateway=172.24.10.254 \

my-web-net03

删除自定义网桥网络

# docker network ls

NETWORK ID NAME DRIVER SCOPE

e22a6ab223fe bridge bridge local

15b417347346 host host local

899362727b48 my-web-net01 bridge local

49352768c5dd my-web-net02 bridge local

7e29b5afd1be my-web-net03 bridge local

5926c0bd11d0 none null local

# docker network rm my-web-net01

或者指量删除

# docker network rm $(docker network ls -f name=my-web -q) #该命令含义是将名字包含my-web的网络列出并删除

同一个自定义网桥中的容器通过容器名互相访问

1、创建自定义网络my-web-net01

# docker network create my-web-net01

2、创建容器t01、t02并使用my-web-net01网络

# docker run -idt --network=my-web-net01 --name t01 busybox /bin/sh

# docker run -idt --network=my-web-net01 --name t02 busybox /bin/sh

3、使用ping命令分别从t01、t02使用容器名进行互ping,验证网络的互通性

# docker exec -it t01 ping t02

# docker exec -it t01 ping t02

结论:同一自定义网络中的容器可以通过容器名互相访问

在默认网桥中的容器不能通过容器名互相访问

1、在默认网桥中创建t03、t04容器

# docker run -idt --name=t03 busybox /bin/sh

# docker run -idt --name=t04 busybox /bin/sh

2、使用ping命令分别从t03、t04使用容器名进行互ping,验证网络的互通性

# docker exec -it t03 ping t04

ping: bad address 't04'

# docker exec -it t04 ping t03

ping: bad address 't03'

3、使用ping命令分别从t03、t04使用ip地址互ping,验证网络的互通性

# docker exec -it t03 ifconfig

# docker exec -it t04 ifconfig

# docker exec -it t03 ping 172.17.0.6

# docker exec -it t04 ping 172.17.0.4

结论:在默认网桥中的容器不能通过容器名互相访问,但可以通过ip互访。

自定义网桥中的容器,可以动态切换容器间的网络连接

1、创建自定义网桥my-web-net02

# docker network create my-web-net02

2、将在my-web-net01网桥中的容器t02同时加到my-web-net02网络中,然后查看t02的网络,如图1.1所示,发现t02多了一个eth2网卡。

# docker network connect my-web-net02 t02

图1.1

3、将t02移出my-web-net01网络,然后,我们再次查看t02的网络连接,如图1.2所示,发现只有eth2网卡了

# docker network disconnect my-web-net01 t02

4、再次验证t02是否还能与t01互通,如图1.3所示。

图1.3

结论:默认已经不能互通,即使用ip也不能,因为t01属于my-web-net01,t02属于my-web-net02。

5、将t02加回到my-web-net01网络,验证互通性,如图1.4所示。

# docker network connect my-web-net01 t02

图1.4

结论:t01与t02可以互通。

将默认网桥中的容器,加入到自定义网桥,验证互通性

1、将t03加入到自定义网桥my-web-net01中,并验证t03与t01和t04的互通性,如图1.5所示。


图1.5

2、将容器从某网络中移除再重新加入网卡名会发生变化,如图1.6所示。

图1.6

总结

不管是自定义网桥还是默认网桥中的容器,均支持动态切换容器间的网络连接,另外,容器在做网络切换时网卡名称会发生变化(重启容器后名称会恢复),这对于需要绑定网卡名称的应用会存在问题,比如阿里的tair缓存。

心之所愿,无事不成,加油!
返回云计算教程...