桥接网络驱动程序
在网络方面,网桥网络是一种链路层设备,用于在网段之间转发流量。网桥可以是硬件设备,也可以是在主机内核中运行的软件设备。
在 Docker 中,网桥网络使用一个软件网桥,允许连接到同一网桥网络的容器进行通信,同时提供与未连接到该网桥网络的容器的隔离。Docker 网桥驱动程序会自动在主机中安装规则,以便不同网桥网络上的容器无法直接相互通信。
网桥网络适用于在同一个 Docker 守护程序主机上运行的容器。对于在不同 Docker 守护程序主机上运行的容器之间的通信,您可以在操作系统级别管理路由,或者可以使用覆盖网络。
当您启动 Docker 时,会自动创建一个默认网桥网络(也称为 `bridge`),新启动的容器除非另有指定,否则会连接到它。您还可以创建用户定义的自定义网桥网络。用户定义的网桥网络优于默认的 `bridge` 网络。
用户定义的网桥与默认网桥之间的差异
用户定义的网桥提供容器间的自动 DNS 解析.
默认网桥网络上的容器只能通过 IP 地址相互访问,除非您使用被视为旧版的 `--link` 选项。在用户定义的网桥网络上,容器可以通过名称或别名相互解析。
想象一个包含 Web 前端和数据库后端的应用程序。如果您将容器命名为 `web` 和 `db`,那么无论应用程序堆栈在哪台 Docker 主机上运行,Web 容器都可以通过 `db` 连接到数据库容器。
如果您在默认网桥网络上运行相同的应用程序堆栈,则需要手动在容器之间创建链接(使用旧的 `--link` 标志)。这些链接需要在两个方向上创建,因此当需要通信的容器超过两个时,这会变得很复杂。或者,您也可以操作容器内的 `/etc/hosts` 文件,但这会产生难以调试的问题。
用户定义的网桥提供更好的隔离性.
所有未指定 `--network` 的容器都会附加到默认网桥网络。这可能存在风险,因为不相关的堆栈/服务/容器随后能够相互通信。
使用用户定义的网络提供了一个作用域网络,其中只有附加到该网络的容器才能通信。
容器可以动态地附加到和分离自用户定义的网络.
在容器的生命周期内,您可以动态地将其连接到或断开与用户定义网络的连接。要从默认网桥网络中移除容器,您需要停止容器并使用不同的网络选项重新创建它。
每个用户定义的网络都会创建一个可配置的网桥.
如果您的容器使用默认网桥网络,您可以对其进行配置,但所有容器都使用相同的设置,例如 MTU 和 `iptables` 规则。此外,配置默认网桥网络是在 Docker 外部进行的,并且需要重新启动 Docker。
用户定义的网桥网络是使用 `docker network create` 创建和配置的。如果不同的应用程序组有不同的网络要求,您可以在创建每个用户定义的网桥时单独配置它。
默认网桥网络上链接的容器共享环境变量.
最初,在两个容器之间共享环境变量的唯一方法是使用 `--link` 标志将它们链接起来。这种变量共享方式不适用于用户定义的网络。然而,有更好的方法来共享环境变量。一些思路如下:
连接到同一用户定义网桥网络的容器实际上会向彼此公开所有端口。为了使端口可被不同网络上的容器或非 Docker 主机访问,该端口必须使用 `-p` 或 `--publish` 标志进行发布。
选项
下表描述了在使用 `bridge` 驱动程序创建自定义网络时,可以传递给 `--opt` 的驱动程序特定选项。
| 选项 | 默认值 | 描述 |
|---|---|---|
com.docker.network.bridge.name | 创建 Linux 网桥时要使用的接口名称。 | |
com.docker.network.bridge.enable_ip_masquerade | true | 启用 IP 伪装。 |
com.docker.network.bridge.gateway_mode_ipv4com.docker.network.bridge.gateway_mode_ipv6 | nat | 控制外部连接。请参阅数据包过滤和防火墙。 |
com.docker.network.bridge.enable_icc | true | 启用或禁用容器间连接。 |
com.docker.network.bridge.host_binding_ipv4 | 所有 IPv4 和 IPv6 地址 | 绑定容器端口时的默认 IP。 |
com.docker.network.driver.mtu | `0` (无限制) | 设置容器网络的最大传输单元 (MTU)。 |
com.docker.network.container_iface_prefix | eth | 为容器接口设置自定义前缀。 |
com.docker.network.bridge.inhibit_ipv4 | false | 防止 Docker 为网桥分配 IP 地址。 |
其中一些选项也可用作 `dockerd` CLI 的标志,您可以在启动 Docker 守护程序时使用它们来配置默认的 `docker0` 网桥。下表显示了哪些选项在 `dockerd` CLI 中有等效的标志。
| 选项 | 标志 |
|---|---|
com.docker.network.bridge.name | - |
com.docker.network.bridge.enable_ip_masquerade | --ip-masq |
com.docker.network.bridge.enable_icc | --icc |
com.docker.network.bridge.host_binding_ipv4 | --ip |
com.docker.network.driver.mtu | --mtu |
com.docker.network.container_iface_prefix | - |
Docker 守护程序支持一个 `--bridge` 标志,您可以用它来定义自己的 `docker0` 网桥。如果您想在同一主机上运行多个守护程序实例,请使用此选项。有关详细信息,请参阅运行多个守护程序。
默认主机绑定地址
当端口发布选项(如 `-p 80` 或 `-p 8080:80`)中没有给出主机地址时,默认情况下会在所有主机地址(IPv4 和 IPv6)上提供容器的 80 端口。
网桥网络驱动程序选项 `com.docker.network.bridge.host_binding_ipv4` 可用于修改已发布端口的默认地址。
尽管选项名称如此,但也可以指定 IPv6 地址。
当默认绑定地址是分配给特定接口的地址时,容器的端口将只能通过该地址访问。
将默认绑定地址设置为 `::` 意味着已发布的端口将仅在主机的 IPv6 地址上可用。但是,将其设置为 `0.0.0.0` 意味着它将在主机的 IPv4 和 IPv6 地址上都可用。
要将已发布的端口限制为仅 IPv4,必须在容器的发布选项中包含该地址。例如,`-p 0.0.0.0:8080:80`。
管理用户定义的网桥
使用 `docker network create` 命令创建一个用户定义的网桥网络。
$ docker network create my-net
您可以指定子网、IP 地址范围、网关和其他选项。有关详细信息,请参阅 docker network create 参考或 `docker network create --help` 的输出。
使用 `docker network rm` 命令删除用户定义的网桥网络。如果当前有容器连接到该网络,请先断开它们的连接。
$ docker network rm my-net
究竟发生了什么?
当您创建或删除用户定义的网桥,或者从用户定义的网桥连接或断开容器时,Docker 会使用操作系统特定的工具来管理底层的网络基础设施(例如在 Linux 上添加或删除网桥设备或配置 `iptables` 规则)。这些细节应被视为实现细节。让 Docker 为您管理用户定义的网络。
将容器连接到用户定义的网桥
当您创建新容器时,可以指定一个或多个 `--network` 标志。此示例将一个 Nginx 容器连接到 `my-net` 网络。它还将容器中的 80 端口发布到 Docker 主机上的 8080 端口,以便外部客户端可以访问该端口。连接到 `my-net` 网络的任何其他容器都可以访问 `my-nginx` 容器上的所有端口,反之亦然。
$ docker create --name my-nginx \
--network my-net \
--publish 8080:80 \
nginx:latest
要将一个**正在运行**的容器连接到现有的用户定义网桥,请使用 `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
在用户定义的网桥网络中使用 IPv6
当您创建网络时,可以指定 `--ipv6` 标志以启用 IPv6。
$ docker network create --ipv6 --subnet 2001:db8:1234::/64 my-net
如果您不提供 `--subnet` 选项,将自动选择一个唯一本地地址(ULA)前缀。
仅 IPv6 的网桥网络
要跳过网桥及其容器中的 IPv4 地址配置,请使用选项 `--ipv4=false` 创建网络,并使用 `--ipv6` 启用 IPv6。
$ docker network create --ipv6 --ipv4=false v6net
在默认网桥网络中无法禁用 IPv4 地址配置。
使用默认网桥网络
默认的 `bridge` 网络被认为是 Docker 的一个遗留细节,不建议在生产环境中使用。配置它是一个手动操作,并且存在技术缺陷。
将容器连接到默认网桥网络
如果您未使用 `--network` 标志指定网络,并且您指定了网络驱动程序,您的容器默认会连接到 `bridge` 网络。连接到默认 `bridge` 网络的容器可以通信,但只能通过 IP 地址,除非它们使用旧版的 `--link` 标志进行链接。
配置默认网桥网络
要配置默认的 `bridge` 网络,您需要在 `daemon.json` 中指定选项。这是一个指定了几个选项的 `daemon.json` 示例。只指定您需要自定义的设置。
{
"bip": "192.168.1.1/24",
"fixed-cidr": "192.168.1.0/25",
"mtu": 1500,
"default-gateway": "192.168.1.254",
"dns": ["10.20.1.2","10.20.1.3"]
}在此示例中:
- 网桥的地址是 "192.168.1.1/24" (来自 `bip`)。
- 网桥网络的子网是 "192.168.1.0/24" (来自 `bip`)。
- 容器地址将从 "192.168.1.0/25" (来自 `fixed-cidr`) 中分配。
在默认网桥网络中使用 IPv6
可以使用 `daemon.json` 中的以下选项或其命令行等效项为默认网桥启用 IPv6。
这三个选项仅影响默认网桥,用户定义的网络不使用它们。以下地址是 IPv6 文档范围内的示例。
- 选项 `ipv6` 是必需的。
- 选项 `bip6` 是可选的,它指定默认网桥的地址,该地址将被容器用作默认网关。它还指定了网桥网络的子网。
- 选项 `fixed-cidr-v6` 是可选的,它指定 Docker 可以自动分配给容器的地址范围。
- 前缀通常应为 `/64` 或更短。
- 对于在本地网络上进行实验,使用唯一本地地址(ULA)前缀(匹配 `fd00::/8`)比使用链路本地前缀(匹配 `fe80::/10`)更好。
- 选项 `default-gateway-v6` 是可选的。如果未指定,默认值为 `fixed-cidr-v6` 子网中的第一个地址。
{
"ipv6": true,
"bip6": "2001:db8::1111/64",
"fixed-cidr-v6": "2001:db8::/64",
"default-gateway-v6": "2001:db8:abcd::89"
}如果未指定 `bip6`,则 `fixed-cidr-v6` 定义了网桥网络的子网。如果未指定 `bip6` 或 `fixed-cidr-v6`,则将选择一个 ULA 前缀。
重新启动 Docker 以使更改生效。
网桥网络的连接限制
由于 Linux 内核的限制,当 1000 个或更多容器连接到单个网络时,网桥网络会变得不稳定,容器间的通信可能会中断。
有关此限制的更多信息,请参阅 moby/moby#44973。
跳过网桥 IP 地址配置
网桥通常被分配网络的 `--gateway` 地址,该地址用作从网桥网络到其他网络的默认路由。
通过 `com.docker.network.bridge.inhibit_ipv4` 选项,您可以创建一个网络,而不会将 IPv4 网关地址分配给网桥。如果您想手动为网桥配置网关 IP 地址,这将非常有用。例如,如果您将一个物理接口添加到您的网桥,并需要它具有网关地址。
使用此配置,除非您已手动在网桥或连接到它的设备上配置了网关地址,否则南北向流量(进出网桥网络的流量)将无法工作。
此选项只能与用户定义的网桥网络一起使用。
后续步骤
- 浏览独立网络教程
- 了解从容器角度看网络
- 了解覆盖网络
- 了解Macvlan 网络