docker 容器在桥接网络模式下无法访问互联网

docker 容器在桥接网络模式下无法访问互联网

总结 当处于网络模式桥接时,如何修复桥接 docker0 以便能够从我的容器访问互联网?


几周前发生了一次停电,显然破坏了服务器网络配置,一段时间以来,DHCP 服务器没有为机器分配正确的 IP。我设法通过使用配置网络解决了这个问题netplan(我不能保证在停电之前就完成了,它由另一个团队管理)。

然而,docker当网络模式为 时,容器无法访问互联网bridge

从主机上,我可以ping google.com,DNS解析工作正常。其他一切似乎也都正常。但是,当我启动容器(例如:)时,它docker run -it --rm python:3.6.1 /bin/bash不再ping起作用。

以下是我检查过的几件事:

  1. ping容器内不起作用:

ping google.com只是挂起:

root@85deb9b2ae95:/# ping google.com
^C

ping 8.8.8.8丢失所有包裹:

root@85deb9b2ae95:/# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
^C--- 8.8.8.8 ping statistics ---
9 packets transmitted, 0 packets received, 100% packet loss
  1. /etc/resolv.conf在docker容器中看起来没问题:
root@85deb9b2ae95:/# cat /etc/resolv.conf 
# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients directly to
# all known uplink DNS servers. This file lists all configured search domains.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.

nameserver 8.8.8.8
nameserver 1.1.1.1

(和楼主的一样)

  1. docker network inspect bridge我觉得不错:
my_user@my_host:~$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "ba15db4d28312e1e7147704d4b04ed12d5acf3ffc03d5308a61e88171ff21b59",
        "Created": "2022-09-30T12:04:54.442845526Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "85deb9b2ae951810887faf6a89b1980bd4ae35d6a61a1639982a3a6558f8100f": {
                "Name": "strange_fermi",
                "EndpointID": "181fede143c82cee3aff9feec8bfff10daf9fbcbd1e70a69bd99ee51f28ed5e4",
                "MacAddress": "xx:xx:xx:xx:xx:xx",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
  1. ifconfig对我来说看起来很好(这是RUNNING因为容器正在运行):
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 xx::xx:xx:xx:xx  prefixlen 64  scopeid 0x20<link>
        ether xx:xx:xx:xx:xx:xx  txqueuelen 0  (Ethernet)
        RX packets 660  bytes 36996 (36.9 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 263  bytes 26836 (26.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  1. 我在输出中没有看到任何奇怪的东西networkctl
alberto_perdomo@builder02:~$ networkctl
IDX LINK        TYPE     OPERATIONAL SETUP      
  1 lo          loopback carrier     unmanaged  
  2 enp67s0f0   ether    routable    configured 
  3 enp67s0f1   ether    no-carrier  configuring
  4 wlp70s0     wlan     no-carrier  unmanaged  
 60 docker0     bridge   routable    unmanaged

除了 iface enp67s0f1“配置”(我认为这可能与我使用 netplan 配置网络的方式有关)。

  1. 内核路由看上去不错:
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.1.1     0.0.0.0         UG    0      0        0 enp67s0f0
172.17.0.0      0.0.0.0         255.255.255.0   U     0      0        0 enp67s0f0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 enp67s0f0
  1. ip route看起来不错:
default via 192.168.1.1 dev enp67s0f0 proto static 
172.17.0.0/24 dev enp67s0f0 proto kernel scope link src 172.17.0.1 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
192.168.1.0/24 dev enp67s0f0 proto kernel scope link src 192.168.1.32
  1. iptables我觉得还好:
my_user@my_host:~$ sudo iptables --list --table nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere            !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere            

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere
  1. 这些是我当前的 docker 网络:
NETWORK ID     NAME      DRIVER    SCOPE
ba15db4d2831   bridge    bridge    local
938ad254f4d2   host      host      local
72ca52dfdedb   none      null      local

最后,如果我以主机模式运行容器(例如:)docker run -it --rm --net=host python:3.6.1 /bin/bash,DNS解析就可以起作用。

它不能像附加--net=host到我的 docker 命令那样简单,因为该服务器运行一些 CI/CD 管道,这些管道应该能够访问互联网、解析域名等等。

所以基本上,主要问题是当处于网络模式桥接时,如何修复桥接 docker0 以便能够从我的容器访问互联网?

我尝试了几件事,其中包括恢复 docker、重新安装 docker、删除docker0iface 并强制 docker 再次创建它。

如能得到关于如何解决或排除此故障的任何帮助、反馈或评论,我们将不胜感激!

答案1

较窄的路线:

172.17.0.0/24 dev enp67s0f0 proto kernel scope link src 172.17.0.1 

优先于以下路线:

172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 

因此,发往 172.17.0.2 和 172.17.0.254 之间的地址的 IP 数据包将通过enp67s0f0而不是进行路由docker0

例如当容器奇怪的费米尝试ping 8.8.8.8,而其自己的传出数据包可能被处理(除非主机设置rp_filter为 1安全防御框架协议) 回复数据包返回到主机 192.168.1.32 地址(因为它们经过了 SNAT),然后被iptablesDocker 按照预期设置了规则,以返回 172.17.0.2。

但是这个新的目的地 172.17.0.2 是通过接口enp67s0f0而不是路由的docker0,并且丢失了:容器无法通信。

立即修复是删除此地址:

ip address delete 172.17.0.1/24 dev enp67s0f0

当然,完成此操作后的配置也必须进行相应的修改。

相关内容