Docker Bridge与主机网络冲突

时间:2018-05-24 16:39:06

标签: docker docker-machine

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

当前的问题是,当此网桥处于活动状态时,我的容器无法访问主机网络上的其他系统。

有什么想法吗?

docker版本:

Version 18.03.1-ce-mac65 (24312)

这是创建的桥梁。有时它不是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

2 个答案:

答案 0 :(得分:3)

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

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

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

方法1-创建虚拟的占位符网络

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

172.17.*中找到您主机网络中未使用的4个连续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

请注意此处的/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

注意:在我的设置中,我的Docker桥位于172.20.0.1上。我已经在/etc/docker/daemon.json中修改了bip来做到这一点。有关更多详细信息,请参见this page

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

docker network create foo_test
# c9e1b01f70032b1eff08e48bac1d5e2039fdc009635bfe8ef1fd4ca60a6af143
docker network create bar_test
# 7ad5611bfa07bda462740c1dd00c5007a934b7fc77414b529d0ec2613924cc57

生成的路由表:

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

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

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

方法2 –关闭冲突的网桥

如果您希望暂时避免IP冲突,则可以使用ip linkip link set dev br-xxxxxxx down将冲突的Docker桥接器关闭。这将具有删除路由表中相应的网桥路由条目的效果,而无需修改任何docker元数据。

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

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

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

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

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

面向未来:

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

答案 1 :(得分:1)

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

在此处找到答案:Docker create two bridges that corrupts my internet access