Docker 容器无法在 Fedora 32 中连接到互联网?

Sid*_*ngh 4 networking linux wireless-networking docker docker-compose

问题

我最近创建了一个必须拉出公共 github 存储库的 docker 容器,但是,它无法解析主机 github.com。事实上,它甚至无法执行 ping 命令。

注意:这里的所有网络操作都在构建后的容器内,当容器运行时

ping www.google.comcannot resolve host

它根本无法连接到互联网。

在查看互联网和Docker 文档后

尝试的解决方案

1) 启用Docker 文档中给出的 IP 转发

我尝试启用 IPForwarding 但无济于事。

/usr/lib/systemd/network/80-container-host0.network启用IPForwarding后的内容

...
[Network]
DHCP=yes
LinkLocalAddressing=yes
LLDP=yes
EmitLLDP=customer-bridge
IPForward=true // this line was changed
[DHCP]
UseTimezone=yes
Run Code Online (Sandbox Code Playgroud)

2) 重新创建Stack Overflow 中给出的 Docker Bridge

pkill docker
iptables -t nat -F
ifconfig docker0 down
brctl delbr docker0
sudo service restart docker
Run Code Online (Sandbox Code Playgroud)

这个本来对这个问题有效

ubuntu 有一个解决方案,但是我的网络配置没有那个有问题的线路

sudo pico /etc/NetworkManager/NetworkManager.conf的只是充满了评论

[main]
#plugins=ifcfg-rh


[logging]
#level=TRACE
#domains=ALL

Run Code Online (Sandbox Code Playgroud)

3) 安装 IP-Tables 服务StackOverflow

sudo yum install iptables-services
sudo service docker restart

Run Code Online (Sandbox Code Playgroud)

4) 在 docker-compose- StackOverflow 中覆盖 DNS 配置

version: "3.3"
services:
    airflow:
        build: 
            context: ./airflow
            dockerfile: Dockerfile
        ports: 
            - 8080:8080
        environment: 
            GITHUB_DAG_REPO: https://github.com/siddharths067/HelloAirflow.git
        dns:
            - 8.8.8.8
            - 8.8.4.4
Run Code Online (Sandbox Code Playgroud)

Docker 网络检查镜像网络

不知道这个有没有用

docker network inspect airflowsetup_default 
[
    {
        "Name": "airflowsetup_default",
        "Id": "141a518c1440e603f75774c54f42de33e9173e3f062a0a0bc772db13a7f1ef5d",
        "Created": "2020-08-30T14:42:30.951975699+05:30",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "airflowsetup",
            "com.docker.compose.version": "1.25.4"
        }
    }
]
Run Code Online (Sandbox Code Playgroud)

输出

airflow_1  | GITHUB DAG REPO IS
airflow_1  | https://github.com/siddharths067/HelloAirflow.git
airflow_1  | Cloning into 'HelloAirflow'...
airflow_1  | fatal: unable to access 'https://github.com/siddharths067/HelloAirflow.git/': Could not resolve host: github.com
Run Code Online (Sandbox Code Playgroud)

Kon*_*tor 5

事件虽然 OP 找到了解决他的问题的方法并关闭了这个问题,但他没有找到根本问题。Docker 的默认桥接网络bridge连接到 Internet的事实airflowsetup_default并不表明 Docker 网络设置有问题。

我做了一些研究,结果 Fedora 32 决定它并不真正关心 Docker 是否在它上面工作。

甚至无法以文档中描述的方式安装 Docker,如果您安装 Fedora 提供的软件包,它仍然无法正常工作 - 有关该问题的更多信息可以在此处此处此处找到

主要问题是,如果容器连接到任何自定义桥接网络,则容器内部没有 Internet 连接——无论它是使用docker network createdocker-compose创建的还是由 docker-compose创建的。

原因很简单——Docker 假设操作系统使用的防火墙iptables,但 Fedora 32默认使用firewalld。这意味着 Docker 不能手动配置防火墙——它必须手动配置。

出于参考目的,我将首先描述如何在干净的 Fedora 32 安装上设置 Docker。

首先运行以下命令:

sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=0"
sudo groupadd docker
sudo usermod -aG docker $USER
Run Code Online (Sandbox Code Playgroud)

这将配置 cgroups 以与 Docker 守护程序兼容,并允许您的用户在没有 sudo 的情况下使用 Docker CLI。

接下来重新启动系统以应用更改并运行:

sudo dnf install -y moby-engine docker-compose nano
sudo systemctl enable docker
sudo systemctl start docker
Run Code Online (Sandbox Code Playgroud)

安装和启用 Docker。

现在转到包含您的目录docker-compose.yml并运行docker-compose up -d. Yuo 应该会看到docker-compose为您创建网络,然后创建容器。如果您的容器在启动时需要互联网连接(如 OP),它将无法启动。

现在运行sudo iptables-save | grep DOCKER,您应该会看到如下内容:

:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o br-b56fa303f315 -j DOCKER
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-b56fa303f315 ! -o br-b56fa303f315 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-b56fa303f315 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A DOCKER -i docker0 -j RETURN
-A DOCKER -i br-b56fa303f315 -j RETURN
Run Code Online (Sandbox Code Playgroud)

docker0是 Docker 的默认桥接网络,而br-b56fa303f315是由docker-compose(您的名称可能不同)创建的新网络。如果您的操作系统正在使用iptables一切都会按预期工作,但事实并非如此,因此我们需要检查docker0in的配置firewalld

运行firewall-cmd --get-active-zones,你会得到类似的东西:

docker
  interfaces: docker0
public
  interfaces: eth0 eth1
Run Code Online (Sandbox Code Playgroud)

您可以看到bridge网络在docker区域中,但新网络不在。实际上它根本没有列出,这意味着它在默认区域中。您可以通过运行来检查那是什么firewall-cmd --get-default-zone。在 Fedora 32 的全新安装中,它是public.

所以运行(记得br-b56fa303f315用你的接口名称替换):

sudo firewall-cmd --zone=docker --add-interface=br-b56fa303f315
Run Code Online (Sandbox Code Playgroud)

docker-compose up -d如果您的服务之前未能启动,则运行,瞧 - 您的容器具有网络连接。

不幸的是,如果您重新启动系统,它将再次失去连接。

您可以使用以下方法防止这种情况:

sudo firewall-cmd --permanent --zone=docker --add-interface=br-b56fa303f315
sudo firewall-cmd --reload
Run Code Online (Sandbox Code Playgroud)

但是,如果您创建任何新网络或重新创建现有网络(例如通过运行docker-compose down然后docker-compose up -d再次运行),您将不得不重复该过程。

那么这个问题的解决方案是什么?

首先,记下当前连接到默认区域的所有网络接口 - 在本例中eth0eth1.

然后运行以下命令(替换public为您的默认区域名称)

sudo firewall-cmd --set-default-zone=docker
sudo firewall-cmd --permanent --zone=public --add-interface=eth0
sudo firewall-cmd --permanent --zone=public --add-interface=eth1
sudo firewall-cmd --reload
Run Code Online (Sandbox Code Playgroud)

现在,之前在默认区域中的接口应该会再次出现,但是所有新接口(以及所有新的 Docker 网络)都将自动添加到docker区域,这将为它们提供完整的网络连接。

  • 我认为将默认区域设置为 `docker` 是最好的解决方案,但您也可以尝试强制 `firewalld` 使用 `iptables`,如下所述:https://dev.to/ozorest/fedora-32-how-to -solve-docker-internal-network-issue-22me (2认同)