桥接网络驱动程序

在网络术语中,桥接网络是一种链路层设备,用于在网络分段之间转发流量。桥接可以是硬件设备,也可以是在主机内核中运行的软件设备。

在 Docker 术语中,桥接网络使用软件桥接,它允许连接到同一桥接网络的容器相互通信,同时提供与未连接到该桥接网络的容器的隔离。Docker 桥接驱动程序会自动在主机上安装规则,以便不同桥接网络上的容器无法直接相互通信。

桥接网络适用于在同一 Docker 守护进程主机上运行的容器。对于在不同 Docker 守护进程主机上运行的容器之间的通信,您可以在 OS 级别管理路由,也可以使用 overlay 网络

当您启动 Docker 时,会自动创建一个默认桥接网络(也称为 bridge),除非另有指定,否则新启动的容器会连接到它。您还可以创建用户定义的自定义桥接网络。用户定义的桥接网络优于默认的 bridge 网络。

用户定义桥接与默认桥接的区别

  • 用户定义桥接提供容器之间的自动 DNS 解析.

    默认桥接网络上的容器只能通过 IP 地址访问彼此,除非使用被认为是传统的 --link 选项。在用户定义的桥接网络上,容器可以通过名称或别名相互解析。

    想象一个包含 Web 前端和数据库后端的应用程序。如果您将容器命名为 webdb,则无论应用程序堆栈在哪台 Docker 主机上运行,Web 容器都可以通过 db 连接到 db 容器。

    如果您在默认桥接网络上运行相同的应用程序堆栈,则需要手动创建容器之间的链接(使用传统的 --link 标志)。这些链接需要在两个方向上创建,因此对于需要通信的容器超过两个时,这会变得复杂。或者,您可以操作容器内的 /etc/hosts 文件,但这会产生难以调试的问题。

  • 用户定义桥接提供更好的隔离.

    所有未指定 --network 的容器都附加到默认桥接网络。这可能存在风险,因为不相关的堆栈/服务/容器随后可以相互通信。

    使用用户定义网络提供了一个范围化的网络,在该网络中只有连接到该网络的容器才能通信。

  • 容器可以动态地从用户定义网络附加或分离.

    在容器的生命周期内,您可以动态地将其连接或断开与用户定义网络的连接。要将容器从默认桥接网络中移除,您需要停止容器并使用不同的网络选项重新创建它。

  • 每个用户定义网络都创建一个可配置的桥接.

    如果您的容器使用默认桥接网络,您可以对其进行配置,但所有容器都使用相同的设置,例如 MTU 和 iptables 规则。此外,默认桥接网络的配置发生在 Docker 本身之外,并且需要重启 Docker。

    用户定义桥接网络是使用 docker network create 创建和配置的。如果不同的应用程序组有不同的网络需求,您可以在创建每个用户定义桥接时单独进行配置。

  • 默认桥接网络上的链接容器共享环境变量.

    最初,在两个容器之间共享环境变量的唯一方法是使用 --link 标志链接它们。这种变量共享类型在用户定义网络中是不可能的。然而,有更好的方法来共享环境变量。一些思路:

    • 多个容器可以使用 Docker 卷挂载包含共享信息的文件或目录。

    • 可以使用 docker-compose 一起启动多个容器,并且 compose 文件可以定义共享变量。

    • 您可以使用 swarm 服务代替独立容器,并利用共享的 secretsconfigs

连接到同一用户定义桥接网络的容器实际上向彼此暴露所有端口。要使端口可供不同网络上的容器或非 Docker 主机访问,必须使用 -p--publish 标志发布该端口。

选项

下表描述了使用 bridge 驱动程序创建自定义网络时可以传递给 --opt 的驱动程序特定选项。

选项默认值描述
com.docker.network.bridge.name创建 Linux 桥接时使用的接口名称。
com.docker.network.bridge.enable_ip_masqueradetrue启用 IP 伪装。
com.docker.network.bridge.gateway_mode_ipv4
com.docker.network.bridge.gateway_mode_ipv6
nat控制外部连接。请参阅 包过滤和防火墙
com.docker.network.bridge.enable_icctrue启用或禁用容器间连接。
com.docker.network.bridge.host_binding_ipv4所有 IPv4 和 IPv6 地址绑定容器端口时的默认 IP。
com.docker.network.driver.mtu0 (无限制)设置容器网络的最大传输单元 (MTU)。
com.docker.network.container_iface_prefixeth为容器接口设置自定义前缀。
com.docker.network.bridge.inhibit_ipv4false阻止 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)中未提供主机地址时,默认设置是使容器的端口 80 在所有主机地址(IPv4 和 IPv6)上可用。

桥接网络驱动程序选项 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 定义桥接网络的子网。如果未指定 bip6fixed-cidr-v6,则会选择一个 ULA 前缀。

重启 Docker 以使更改生效。

桥接网络的连接限制

由于 Linux 内核设置的限制,当 1000 个或更多容器连接到单个网络时,桥接网络会变得不稳定,容器间通信可能会中断。

有关此限制的更多信息,请参阅 moby/moby#44973

跳过桥接 IP 地址配置

网桥通常被分配网络的 --gateway 地址,该地址用作从桥接网络到其他网络的默认路由。

com.docker.network.bridge.inhibit_ipv4 选项允许您创建一个不将 IPv4 网关地址分配给网桥的网络。如果您想手动配置网桥的网关 IP 地址,这会很有用。例如,如果您将一个物理接口添加到网桥并需要它具有网关地址。

使用此配置,南北向流量(进出桥接网络的流量)将无法工作,除非您已在网桥或连接到它的设备上手动配置了网关地址。

此选项只能用于用户定义的桥接网络。

下一步

页面选项