Docker Bridge与主机网络冲突

Pau*_*uca 7 docker docker-machine

在容器开始运行之后,Docker似乎正在创建一个桥,然后与我的主机网络发生冲突。这不是默认桥docker0,而是在容器启动后创建的另一个桥。我能够根据旧的用户指南链接https://docs.docker.com/v17.09/engine/userguide/networking/default_network/custom-docker0/配置默认桥,但是,我不知道如何配置另一个网桥,以使其与172.17不冲突。

那么,当前的问题是,当该网桥变为活动状态时,我的容器无法访问主机网络上的其他系统。

有任何想法吗?

码头工人的版本:

Version 18.03.1-ce-mac65 (24312)
Run Code Online (Sandbox Code Playgroud)

这就是创建的桥梁。有时不是172.17,但有时是。

br-f7b50f41d024 Link encap:Ethernet  HWaddr 02:42:7D:1B:05:A3  
      inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
Run Code Online (Sandbox Code Playgroud)

ini*_*_js 7

当创建docker网络(例如使用docker network createdocker-compose或通过docker-compose间接)而未明确指定子网范围时,dockerd分配一个新/16网络,从开始172.N.0.0/16,其中N的数字是递增的(例如N = 17,N = 18,N = 19,N = 20,...)。N如果范围内已经有docker网络:自定义docker网络或默认docker网桥,则跳过给定的给定值。

创建新的桥接网络时,可以明确指定要使用的IP范围,以避免冲突。不幸的是,这样做将需要修改您遇到的每个docker-compose.yaml文件-以明确提供一个安全的IP块。通常,人们希望避免在撰写文件中包含特定于主机的内容。

相反,您可以使用docker认为已分配的网络。我概述了以下3种方法,这些方法应允许您强制dockerd“跳过”子网。

方法#1-创建一个虚拟占位符网络

您可以172.17.0.0/16通过在内部的任何地方创建一个非常小的docker网络来阻止整个dockerd使用(在将来的网桥网络中)172.17.0.0/16

172.17.*您知道主机网络中没有使用的四个连续IP中,将它们牺牲在“逻辑删除”泊坞桥中。下面,我假设了IPS 172.17.253.0172.17.253.1172.17.253.2172.17.253.3(即172.17.253.0/30)是您的主机的网络中使用。

docker network create --driver=bridge --subnet 172.17.253.0/30 tombstone
# created: c48327b0443dc67d1b727da3385e433fdfd8710ce1cc3afd44ed820d3ae009f5
Run Code Online (Sandbox Code Playgroud)

请注意/30此处的后缀,它是4个不同的IP。从理论上讲,最小的有效网络子网应该是,/31它由总共2个IP(网络标识符+广播)组成。Docker要求一个/30最低限度,可能要考虑一个网关主机和另一个容器。我.253.0任意选择,您应该选择环境中未使用的东西。还要注意,标识符tombstone没有什么特别的,您可以将其重命名为可以帮助您记住几个月后再次找到它的原因。

如果查看路由表,将看到新网桥的条目:

# output of route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.5.1     0.0.0.0         UG    0      0        0 eth1
172.17.253.0    0.0.0.0         255.255.255.252 U     0      0        0 br-c48327b0443d
172.20.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.5.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
Run Code Online (Sandbox Code Playgroud)

注意:在我的设置中,我的Docker桥位于172.20.0.1上。我已经bip在/etc/docker/daemon.json中进行了修改。有关更多详细信息,请参见此页面

现在,如果我们创建新的docker网络,我们可以看到其余的172.17.0.0/16被跳过了,因为范围并不完全可用。

docker network create foo_test
# c9e1b01f70032b1eff08e48bac1d5e2039fdc009635bfe8ef1fd4ca60a6af143
docker network create bar_test
# 7ad5611bfa07bda462740c1dd00c5007a934b7fc77414b529d0ec2613924cc57
Run Code Online (Sandbox Code Playgroud)

生成的路由表:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.5.1     0.0.0.0         UG    0      0        0 eth1
172.17.253.0    0.0.0.0         255.255.255.252 U     0      0        0 br-c48327b0443d
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-c9e1b01f7003
172.19.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-7ad5611bfa07
172.20.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.5.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
Run Code Online (Sandbox Code Playgroud)

注意,其余的IP 172.17.0.0/16尚未使用。新的网络已保留.18..19.。将通信发送到该逻辑删除网络外部的任何冲突IP都将通过您的主机网络。

您将必须在docker中保留该逻辑删除网络,但不能在容器中使用它。这是一个虚拟的占位符网络。

方法#2-关闭冲突的网桥网络

如果你想暂时避开IP冲突,可以带来冲突的泊坞窗桥下来使用ip linkip link set dev br-xxxxxxx down。这将具有删除路由表中对应的网桥路由条目的效果,而无需修改任何docker元数据。

可以说这不是上面的方法的好方法,因为您可能必须在每次dockerd启动时关闭接口,并且如果有任何容器正在使用该网桥,那么它将干扰您的容器网络。

如果方法1在将来停止工作(例如,因为docker尝试变得更聪明并重用了ip块的未使用部分),则可以将两种方法结合起来:例如,创建一个具有整个网络的大型墓碑网络/16,而不在任何容器中使用它,以及然后关闭其相应的br-x设备。

方法#3-重新配置您的Docker桥以占用冲突的/ 16的子部分

作为上述内容的略微变化,您可以使默认Docker桥与172.17.*.*您的主机网络中未使用的区域重叠。您可以通过在中更改网桥IP(即bip密钥)来更改默认的Docker网桥子网/etc/docker/daemon.json(有关更多详细信息,请参阅此页面)。只需将其设为/ 16的子区域即可,例如/ 24或更小。

我尚未对此进行测试,但是我认为任何新的docker网络都将跳过其余部分,172.17.0.0/16/16为每个新网桥分配完全不同的网络。

为将来:

我一直在寻找一种为新的网桥配置dockerd的起始IP范围不同的方法,但是找不到任何东西(从1.13.1版开始)。希望将来会有所改变。能够指定要排除的IP范围似乎是需要的。


Pau*_*uca 3

该桥是从 docker-compose 创建的,可以在 compose 文件中进行配置。

答案在这里找到:Docker 创建了两个破坏我的互联网访问的网桥