桥接网络驱动

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

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

桥接网络适用于运行在同一Docker守护进程主机上的容器。对于运行在不同Docker守护进程主机上的容器之间的通信,您可以在操作系统级别管理路由,或者可以使用覆盖网络

当你启动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文件可以定义共享变量。

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

连接到同一用户定义桥接网络的容器实际上会相互暴露所有端口。要使不同网络上的容器或非Docker主机能够访问某个端口,必须使用-p--publish标志发布该端口。

选项

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

OptionDefaultDescription
com.docker.network.bridge.nameInterface name to use when creating the Linux bridge.
com.docker.network.bridge.enable_ip_masqueradetrueEnable IP masquerading.
com.docker.network.bridge.gateway_mode_ipv4
com.docker.network.bridge.gateway_mode_ipv6
natEnable NAT and masquerading (nat), or only allow direct routing to the container (routed).
com.docker.network.bridge.enable_icctrueEnable or Disable inter-container connectivity.
com.docker.network.bridge.host_binding_ipv4all IPv4 and IPv6 addressesDefault IP when binding container ports.
com.docker.network.driver.mtu0 (no limit)Set the containers network Maximum Transmission Unit (MTU).
com.docker.network.container_iface_prefixethSet a custom prefix for container interfaces.
com.docker.network.bridge.inhibit_ipv4falsePrevent Docker from 分配IP地址 to the network.

其中一些选项也可以作为dockerd CLI的标志使用,您可以在启动Docker守护进程时使用它们来配置默认的docker0桥接。下表显示了哪些选项在dockerd CLI中有等效的标志。

OptionFlag
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

使用默认的桥接网络

默认的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"]
}

重启Docker以使更改生效。

使用默认桥接网络的IPv6

可以通过在daemon.json中使用以下选项,或它们的命令行等效项来为默认桥启用IPv6。

这三个选项仅影响默认桥接,它们不用于用户定义的网络。下面的地址是来自IPv6文档范围的示例。

  • 选项 ipv6 是必需的
  • 选项 fixed-cidr-v6 是必需的,它指定要使用的网络前缀。
    • 前缀通常应为 /64 或更短。
    • 在本地网络上进行实验时,最好使用唯一本地前缀(匹配 fd00::/8)而不是链路本地前缀(匹配 fe80::/10)。
  • 选项 default-gateway-v6 是可选的。如果未指定,默认值为 fixed-cidr-v6 子网中的第一个地址。
{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8::/64",
  "default-gateway-v6": "2001:db8:abcd::89"
}

桥接网络的连接限制

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

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

跳过IP地址配置

com.docker.network.bridge.inhibit_ipv4 选项允许您创建一个使用现有桥接的网络,并让 Docker 跳过在桥接上配置 IPv4 地址。如果您想手动配置桥接的 IP 地址,这将非常有用。例如,如果您将物理接口添加到桥接中,并需要将其 IP 地址移动到桥接接口。

要使用此选项,您应首先配置Docker守护程序以使用自管理的桥接,通过在daemon.json中使用bridge选项或使用dockerd --bridge标志。

使用此配置,南北流量将无法工作,除非您已手动配置桥接的IP地址。

下一步