Docker网路模型(四)使用 bridge 网络

使用 bridge 网络

在计算机网络中,一个 bridge(网桥)是一个链路层设备,负责在不同的网段之间转发信息。 bridge 可以是真实的硬件设备也可以是由宿主机底层提供的软件模拟设备。

在 Docker 中,bridge 网络使用了软件虚拟的网桥,让连接到同一个桥上的容器能互相通讯的同时,也隔离了没有连接到同一个桥上的容器。Docker 的 bridge 网络驱动会自动在宿主机上安装好防火墙规则,隔离开不同网桥之间的直接通讯。

bridge 网络适用于同一个 Docker daemon 宿主机下的容器,对于不同主机之间的通讯,你可以自己在操作系统层面设置路由规则,或者是用 overlay 网络

当你启动 Docker 的时候,一个默认的bridge网络 (也叫 bridge) 会自动创建(参考下文),跟着所有后面启动的容器除非自己有指定,否则都会自动连接到上面。你也可以创建一个自定义的 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 上是共享不了的。但是,我们有更好的办法去共享环境变量。举例:

    • 复数个容器可以用 Docker volume (卷),把共享信息挂载到容器里的某个文件或者路径下。

    • 复数个容器可以用 docker-compose 一起启动,然后可以在 compose file 里面定义共享的变量。

    • 你可以用 swarm 编排工具来管理容器,而不是单独启动,然后可以用上 swarm 的 secrets 和 configs 共享。

所有连接到同一个用户定义的 bridge 都有效地对彼此暴露所有端口。要想让在不同的网络上的容器或者非 Docker 主机能访问到某个端口,需要将此端口用 -p 或者--publish 标志给公开出来。

管理用户定义 bridge

用 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 来管理你的用户定义网络就好。

将某个容器连接到一个用户定义的 bridge 上

当你创建一个新的容器时,可以指定一个或者多个 --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

将某个容器从用户定义的 bridge 上断开

要将一个正在运行的容器从用户定义断开,可使用 docker network disconnect 命令。下面的命令将 my-nginx 容器从 my-net 网中断掉。

$ docker network disconnect my-net my-nginx

使用 IPv6

如果你在 Docker 容器中需要IPv6,那么在创建任意的 IPv6 网络跟给容器分配 IPv6 地址之前, 需要在 Docker daemon 层面 打开对应的选项 并重载配置。

在创建你的网络时,可以用 --ipv6 标志来开启 IPv6。你不能选择性地禁用默认 bridge 网络的 IPv6 支持。

启用从 Docker 容器到外部的转发功能

默认情况下,连接到默认 bridge 的容器的网络流量,不会转发到外部。要想启用转发,你需要修改两处设定。它们不是 Docker 命令,而是在 Docker 的宿主机的内核上生效的。

  1. 配置 Linux 内核,允许 IP 转发(IP forwarding)。

    $ sysctl net.ipv4.conf.all.forwarding=1
    
  2. 修改 iptables 的 FORWARD 策略,从 DROP 修改为 ACCEPT

    $ sudo iptables -P FORWARD ACCEPT
    

这些设置重启之后就没了,所以你可能需要把它们加到启动脚本里。

使用默认的 bridge 网络

默认的 bridge 网络可以看作是一个 Docker 快被遗弃的细节,不建议在生产环境中使用。配置它属于手动操作,而且它有技术缺陷(参考上面提到的两种 bridge 的不同)。

将某个容器连接到默认 bridge 上

如果你不用 --network 标志指定网络,而又指定了网络驱动,你的容器就会连接到默认 bridge 网络。连接到默认的 bridge 网络的容器是可以通讯的,但只能用 IP 地址来进行。除非你用准备遗弃的 --link 标志来连接他们。

配置默认的 bridge 网络

要配置默认的 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 让这些改动生效。

在默认 bridge 网络上使用 IPv6

如果你将 Docker 配置了支持IPv6(参见上面的使用IPv6),默认 bridge 网络也会自动配置为IPv6。与用户定义的 bridge 不同,你不能在默认网桥上选择性地禁用IPv6。

接下来

猜你喜欢

转载自blog.csdn.net/weixin_42445065/article/details/130827936