赞
踩
在计算机网络中,一个 bridge(网桥)是一个链路层设备,负责在不同的网段之间转发信息。 bridge 可以是真实的硬件设备也可以是由宿主机底层提供的软件模拟设备。
在 Docker 中,bridge 网络使用了软件虚拟的网桥,让连接到同一个桥上的容器能互相通讯的同时,也隔离了没有连接到同一个桥上的容器。Docker 的 bridge 网络驱动会自动在宿主机上安装好防火墙规则,隔离开不同网桥之间的直接通讯。
bridge 网络适用于同一个 Docker daemon 宿主机下的容器,对于不同主机之间的通讯,你可以自己在操作系统层面设置路由规则,或者是用 overlay 网络。
当你启动 Docker 的时候,一个默认的bridge网络 (也叫 bridge
) 会自动创建(参考下文),跟着所有后面启动的容器除非自己有指定,否则都会自动连接到上面。你也可以创建一个自定义的 bridge 网络。用户定义的 bridge 网络要优于默认的 bridge 网络。
用户定义的 bridge 提供容器之间的自动 DNS 解析。
在默认 bridge 下的容器只能通过 IP 地址访问彼此,除非使用 --link 选项,此选项已经标记为遗弃状态。而在用户定义的 bridge 网络,容器间可以通过主机名或者别名来解析彼此的地址。
想象有一个应用栈,包含了一个网页前端跟一个数据库后端。假设你分别命名两种容器为 web
和 db
,无论应用栈在哪个 Docker 宿主机跑着,web
容器都能够连接 db
容器里面的数据库。
如果你把这种应用栈跑在默认的 bridge 网络上,你就要手动给两种不同的容器加上链接(用遗弃的 --link
标志)。这些链接在链接的两个方向都要进行设置,可以想象超过两个以上的容器的情况会变得多么复杂。此外,你也可以修改容器里面的 /etc/hosts
文件,但这会产生难以调试的问题。
用户定义的 bridge 提供了更好的隔离。
所有不用 --network
标志的容器都会连接到默认的 bridge 网络上。这是有风险的,这种情况下不相关的 应用栈/服务/容器 能够直接通讯。
而用户定义的 bridge 网络就能够提供限定范围的网络,只有连接到各自的 bridge 上的容器才能互通。
容器能在用户定义的 bridge 上即时插拔。
在容器的生命周期内,你可以在用户定义的 bridge 上即时插拔它们。而你要在默认的 bridge 上删除某个容器时,就需要先停掉容器,然后再重新用不同的网络选项去创建它。
用户定义的网络提供了能灵活配置的 bridge。
如果你的容器使用的是默认的 bridge,你也可以配置,但所有的容器都会使用同一个设置,比如 MTU 大小和 iptables
规则。此外,配置默认 bridge 网络是在 Docker 之外进行的,这就需要 Docker 来一次重启。
而用户定义得 bridge 使用 docker network create
来创建和配置。如果有几组不同的应用需要用到不同的网络,你可以分别给他们创建和配置不同的 bridge。
在默认 bridge 上所有的容器共享环境变量。
一开始,在两个不同的容器之间共享环境变量,只有用 --link 标志一个办法。这样的变量在用户定义的 bridge 上是共享不了的。但是,我们有更好的办法去共享环境变量。举例:
所有连接到同一个用户定义的 bridge 都有效地对彼此暴露所有端口。要想让在不同的网络上的容器或者非 Docker 主机能访问到某个端口,需要将此端口用 -p
或者--publish
标志给公开出来。
用 docker network create
命令来创建一个用户定义 bridge 网络。
$ docker network create my-net
你可以指定子网掩码、IP地址范围、默认网关跟其他的选项。详情参考 docker network create 文档或者 docker network create --help
的输出。
使用 docker network rm
命令来移除一个用户定义 bridge 网络。如果上面有连着的容器,请先参考下文断连它们。
$ docker network rm my-net
这中间发生了什么?
当你创建或移除用户定义的 bridge 或在用户定义的 bridge 上连接或断开某些容器时,Docker 使用操作系统特有的工具来管理底层网络设施(比如在Linux上添加或移除网桥设备或配置
iptables
规则)。这些细节应看作是实现细节,让 Docker 来管理你的用户定义网络就好。
当你创建一个新的容器时,可以指定一个或者多个 --network
标志。此例子把一个 Nginx 容器连在了 my-net
网络上。同时把80端口公开在了宿主机的8080端口上,这样外部的客户端能够访问到这个端口。任何同样连接到 my-net
网络的其他容器,都能够访问到 my-nginx
容器的所有端口,反之亦然。
- $ docker create --name my-nginx \
- --network my-net \
- --publish 8080:80 \
- nginx:latest
要将一个正在运行的容器连接到一个已有的用户定义 bridge,可使用 docker network connect
命令。下面的命令将一个已经跑起来的 my-nginx
容器连到了一个已有的 my-net
网络:
$ docker network connect my-net my-nginx
要将一个正在运行的容器从用户定义断开,可使用 docker network disconnect
命令。下面的命令将 my-nginx
容器从 my-net
网中断掉。
$ docker network disconnect my-net my-nginx
如果你在 Docker 容器中需要IPv6,那么在创建任意的 IPv6 网络跟给容器分配 IPv6 地址之前, 需要在 Docker daemon 层面 打开对应的选项 并重载配置。
在创建你的网络时,可以用 --ipv6
标志来开启 IPv6。你不能选择性地禁用默认 bridge 网络的 IPv6 支持。
默认情况下,连接到默认 bridge 的容器的网络流量,不会转发到外部。要想启用转发,你需要修改两处设定。它们不是 Docker 命令,而是在 Docker 的宿主机的内核上生效的。
配置 Linux 内核,允许 IP 转发(IP forwarding)。
$ sysctl net.ipv4.conf.all.forwarding=1
修改 iptables
的 FORWARD
策略,从 DROP
修改为 ACCEPT
。
$ sudo iptables -P FORWARD ACCEPT
这些设置重启之后就没了,所以你可能需要把它们加到启动脚本里。
默认的 bridge
网络可以看作是一个 Docker 快被遗弃的细节,不建议在生产环境中使用。配置它属于手动操作,而且它有技术缺陷(参考上面提到的两种 bridge 的不同)。
如果你不用 --network
标志指定网络,而又指定了网络驱动,你的容器就会连接到默认 bridge
网络。连接到默认的 bridge
网络的容器是可以通讯的,但只能用 IP 地址来进行。除非你用准备遗弃的 --link 标志来连接他们。
要配置默认的 bridge 网络, 你需要在 daemon.json
中指定选项。下面是一个指定了几个选项的 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(参见上面的使用IPv6),默认 bridge 网络也会自动配置为IPv6。与用户定义的 bridge 不同,你不能在默认网桥上选择性地禁用IPv6。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。