【问题标题】:Docker Bridge Conflicts with Host NetworkDocker Bridge 与主机网络冲突
【发布时间】:2018-05-24 16:39:06
【问题描述】:

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

【问题讨论】:

    标签: docker docker-machine


    【解决方案1】:

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

    在 CLI 上创建 docker 网桥(即排除网络中的主机 ips 的网桥)时,您可以明确指定一个安全的 IP 范围。但通常桥接网络是由 docker-compose 使用默认块自动创建的。要可靠地排除这些 IP,需要修改您遇到的每个 docker-compose.yaml 文件。在撰写文件中包含特定于主机的内容是一种不好的做法。

    相反,您可以使用 docker 认为已分配的网络来强制 dockerd “跳过”子网。我在下面概述了三种方法:

    方法 #0 -- 在 daemon config 中配置 ips 池

    如果您的 docker 版本足够新(TODO 检查最低版本),并且您有权配置 docker 守护程序的命令行参数,则可以尝试将 --default-address-pool ARG 选项传递给 dockerd 命令。例如:

     # allocate /24 subnets with the given CIDR prefix only.
     # note that this prefix excludes 172.17.*
     --default-address-pool base=172.24.0.0/13,size=24
    

    您可以将此设置添加到 etc 文件之一:/etc/default/docker/etc/sysconfig/docker,具体取决于您的发行版。还有一种方法可以在daemon.json中设置这个参数(see syntax

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

    您可以通过在 172.17.0.0/16 内的任何位置创建一个非常小的 docker 网络来防止 dockerd(在未来的桥接网络中)使用整个 172.17.0.0/16

    172.17.* 中找到 4 个您知道在您的主机网络中未使用的连续 IP,并将它们牺牲在“墓碑”docker 桥中。下面,我假设您的主机网络中未使用 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 并没有什么特别之处,您可以将其重命名为任何可以帮助您在几个月后再次找到它时记住它的原因的名称。

    Docker 将修改您的路由表,以使这 4 个 IP 的流量通过新的网桥而不是主机网络:

    # 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
    

    注意:172.17.253.{0,1,2,3} 的流量通过刚刚创建的墓碑码头桥 (br-c4832...)。 172.17.* 中任何其他 IP 的流量将通过默认路由(主机网络)。我的 docker 桥 (docker0) 在 172.20.0.1 上,这可能看起来不寻常——我在 /etc/docker/daemon.json 中修改了 bip 来做到这一点。有关详细信息,请参阅this page

    转折点:如果存在甚至占据 /16 子部分的桥,则创建的新桥将跳过该范围。如果我们创建新的 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 关闭有冲突的 docker 网桥:ip link set dev br-xxxxxxx down(其中 xxxxxx 表示来自 route -nip link show 的网桥网络名称)。这将具有删除路由表中相应网桥路由条目的效果,而无需修改任何 docker 元数据。

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

    如果方法 1 在未来停止工作(例如,因为 docker 试图变得更聪明并重用 ip 块的未使用部分),您可以结合这两种方法:例如用整个/16创建一个大的tombstone网络,不要在任何容器中使用它,然后把它对应的br-x设备down掉。

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

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

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

    【讨论】:

    • 这是一个很好的答案老兄,帮了我很多!
    • /etc/docker/daemon.json 的语法:"default-address-pools":[ {"base":"172.17.0.0/16","size":24} ]跨度>
    • 解决方案#0 的最低版本(目前为止最好的)应该是 Docker 18.09.1(在 linux 上)(参见 github.com/moby/moby/pull/36396
    【解决方案2】:

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

    在这里找到答案:Docker create two bridges that corrupts my internet access

    【讨论】:

      【解决方案3】:

      可能由于您没有在虚拟 oracle 系统上安装 docker-compose 而发生此错误

      apt install docker-compose 
      

      然后尝试工作

      【讨论】:

        猜你喜欢
        • 2021-06-14
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        • 1970-01-01
        • 2017-02-27
        • 2021-04-14
        • 2017-09-12
        相关资源
        最近更新 更多