桥接网络(bridge network)
就网络而言,桥接网络是在网段之间转发流量的链路层设备,可以是硬件设备或在主机内核中运行的软件设备。
就Docker而言,桥接网络使用一个软件网桥,能够使连接到同一网桥的容器相互通信,同时为没有连接到该网桥的容器提供隔离。Docker桥接驱动自动在主机上设置规则,这样在不同桥接网络上的容器之间无法直接相互通信。
桥接网络应用在同一Docker守护进程上的容器。对于运行在不同Docker守护进程上的容器之间的通信,可以在操作系统层面上转发,或使用overlay网络。
当启动Docker时,一个默认的bridge网络自动被创建,除非指定,否则所有新的容器都连接到这个网络。也可以创建用户自定义的bridge网络。用户自定义的bridge网络优先级高于默认的bridge网络。
自定义bridge网络和默认bridge网络的区别
- 用户自定义bridge网络提供容器之间的自动DNS解析
连接到默认bridge网络上容器,相互之间通信只能通过IP,除非创建容器时使用了--link
。在用户自定义bridge网络上,容器之间可以通过名称或简称相互解析。
设想一个应用程序,有一个web前端和一个数据库后端,两个容器分别命名为web
和db
,web容器可以连接到db容器,无论应用在哪个Docker主机上运行着。
如果应用程序连接着默认的bridge网络,你需要使用--link
手动连接两个容器,这种连接需要在容器都创建,因此,对于需要通信的两个以上的容器,这会变得非常复杂。或者可以维护容器内的/etc/hosts
文件,但这种方式如果出现问题时,会非常难定位。
- 用户自定义bridge网络提供更好的隔离
所有没有指定--network
的容器,连接到默认的bridge网络,这是存在风险的,因为不相关的stack、服务或容器可以相互之间通信。
用户自定义的网络提供了一个限定范围的网络,只有连接到该网络上的容器之间可以通信。
- 容器可以动态地与用户自定义网络连接或分离
在一个容器的生命周期内,你可以动态的将其连接或断开用户自定义的网络。为了将一个容器从默认的bridge网络上分开,需要先停止该容器,然后使用不同的网络配置重新创建容器。
- 每个用户自定义的网络创建一个可配置的网桥
如果你的容器使用的默认的bridge网络,你可以配置它,但所有的容器使用相同的配置,比如MTU和iptables
规则。另外,配置默认bridge网络发生在Docker外部,需要重启Docker才能生效。
使用docker network create
创建和配置用户自定义bridge网络。如果不同的应用有不同的网络配置需求,则可以分别配置每个用户自定义的bridge网络。
- 连接到默认bridge网络的容器共享环境变量
起初,两个容器之间共享环境变量的唯一方法是使用--link
连接它们。这种变量共享的方式在用户自定义网络中并不可能。但是,有其他更优先的方法共享环境变量:
- 多个容器可以使用Docker volume挂载一个文件或目录,包含需要共享的信息。
- 多个容器可以使用
docker-compose
同时启动,在compose文件中定义共享变量。 - 可以使用swarm服务代替单个容器,利用共享secrets和configs。
连接到同一用户自定义bridge网络上的容器相互之间有效的暴露端口。对不同网络上的容器或非Docker主机暴露端口,必须使用-p
或--publish
标签。
管理用户自定义网桥
使用docker network create
命令创建用户自定义bridge网络。
docker network create my-net
可以指定子网、IP地址范围、网关及其他配置。可以使用docker network create --help
查看相关帮助。
使用docker network rm
命令删除用户自定义bridge网络。如果有容器连接到该网络,先断开它们。
docker network rm my-net
当你创建或删除一个用户自定义bridge网络,或者是一个容器从用户自定义bridge网络上连接、断开,Docker使用操作系统的特定工具来管理底层的网络基础设施(比如添加或删除桥接设备,或配置Linux上的
iptables
规则),这些涉及到实现细节,让Docker来管理你的用户自定义网络。
将容器连接/断开自定义bridge网络
当你创建一个容器时,你可以指定一个或多个--network
标签。下面的例子将Nginx连接到my-net
网络,同时将容器的80端口暴露到Docker主机上的8080端口,这样外部的客户端可以访问这个端口。其他连接到my-net
的容器可以访问nginx容器的所有端口,反之亦然。
docker create --name my-nginx \
--network my-net \
--publish 8080:80 \
nginx:latest
使用docker network connect
命令可以将一个运行中的容器连接到用户自定义的bridge网络上。下面的命令将一个已经运行的my-nginx
容器连接到已存在的my-network
网络。
docker network connect my-net my-nginx
使用docker network disconnect
命令,将一个在运行的容器从用户自定义bridge网络上断开,下面的命令将在运行的my-nginx
容器从my-net
网络上断开。
docker network disconnect my-net my-nginx
使用IPv6
如果你需要IPv6支持你的Docker容器,在你创建IPv6网络或给容器指定IPv6地址之前,你需要在Docker守护进程上启用该配置并重新加载配置。
当你创建自己网络时,你可以指定--ipv6
标签来启用IPv6。不能选择性的禁用默认bridge网络上的IPv6支持。
使用默认的bridge网络
默认bridge网络被认为是Docker的遗留选项,不建议在生产环境使用。
如果不使用--network
标签指定网络,而是指定了网络驱动,默认情况下,容器连接到默认bridge网络。连接到默认bridge网络上的容器只能通过IP通信,除非你使用了不建议的--link
标签。
为了配置默认bridge网络,可以在daemon.json
文件中指定。下面是一个该文件的例子,指定了几个配置,仅指定需要自定义的配置。
{
"bip": "192.168.1.1/24",
"fixed-cidr": "192.168.1.0/25",
"fixed-cidr-v6": "2001:db8::/64",
"mtu": 1500,
"default-gateway": "192.168.1.254",
"default-gateway-v6": "2001:db8:abcd::89",
"dns": ["10.20.1.2","10.20.1.3"]
}
重启Docker使配置生效。
如果Docker配置了IPv6,默认的bridge网络自动配置了IPv6,和用户自定义bridge不同,不能单独禁用默认网络上的IPv6.
bridge网络的连接限制
由于Linux内核的限制,当超过1000个容器或更多的连接在一个单独的bridge网络时,bridge网络会变得不稳定,容器之间的通信可能会断开。