Docker 守护进程未绑定到 TCP6

Docker 守护进程未绑定到 TCP6

我有一个具有默认网络配置和如下定义的组合:

services:

  myservice:
    image: someimage
    restart: always
    ports:
      - 80:80
      - 443:443

该服务正确绑定到 IPv4,可以按预期访问。一两周以来,该服务不再绑定到 IPv6,而之前运行没有问题。运行netstat -plnt显示 docker-proxy 未监听 IPv6 端口:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      1936/docker-proxy
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1898/docker-proxy
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      811/systemd-resolve
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      1883/docker-proxy
tcp6       0      0 :::2377                 :::*                    LISTEN      1283/dockerd
tcp6       0      0 :::7946                 :::*                    LISTEN      1283/dockerd

因此,您可以看到端口 80 和 443 暴露在 上,tcp但没有tcp6。搜索此问题,我只能找到相反的问题(docker 正在监听 IPv6 而不是 IPv4)。

当尝试绑定端口时,socat会报告端口正在使用(而 则netstat表示未使用)。将端口 81 绑定到端口 80 上的 IPv4 地址允许我通过 IPv6 访问服务器,因此其他地方不会出现路由问题。

sudo socat TCP6-LISTEN:80,fork TCP4:127.0.0.1:80
2021/01/13 16:08:50 socat[26572] E bind(5, {AF=10 [0000:0000:0000:0000:0000:0000:0000:0000]:80}, 28): Address already in use

docker inspect显示以下信息:

"NetworkSettings": {
    "Bridge": "",
    "SandboxID": "d5fdebb4de954a4d7c1800490e44d0f53c4ee827775edb8ba286583e888eaa07",
    "HairpinMode": false,
    "LinkLocalIPv6Address": "",
    "LinkLocalIPv6PrefixLen": 0,
    "Ports": {
        "443/tcp": [
            {
                "HostIp": "0.0.0.0",
                "HostPort": "443"
            }
        ],
        "80/tcp": [
            {
                "HostIp": "0.0.0.0",
                "HostPort": "80"
            }
        ]
    },
    "SandboxKey": "/var/run/docker/netns/d5fdebb4de95",
    "SecondaryIPAddresses": null,
    "SecondaryIPv6Addresses": null,
    "EndpointID": "",
    "Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "IPAddress": "",
    "IPPrefixLen": 0,
    "IPv6Gateway": "",
    "MacAddress": "",
    "Networks": {
        "docker_default": {
            "IPAMConfig": null,
            "Links": null,
            "Aliases": [
                "d8acfbf724cf"
            ],
            "NetworkID": "87b6b52c779252614553040f217f9f2310ee3cce5f1a450f6a8210e8ea411b5a",
            "EndpointID": "a6bdf4d85641a043c25812ac0759a7ad872a3ee15ff7ea0e3ddf6b2405967737",
            "Gateway": "172.20.0.1",
            "IPAddress": "172.20.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "MacAddress": "02:42:ac:14:00:02",
            "DriverOpts": null
        }
    }
}

答案1

这似乎是 Docker 20.10.2 中的半故意的1更改,请参阅此处的相关讨论:https://github.com/moby/libnetwork/issues/2607.看起来像使固定进行

与此同时,降级到 20.10.1 对我来说是可行的:

sudo apt install docker-ce=5:20.10.1~3-0~ubuntu-focal \
                 docker-ce-cli=5:20.10.1~3-0~ubuntu-focal
sudo apt-mark hold docker-ce docker-ce-cli

1半故意的,因为显然,这个功能从未打算以这种方式使用。我和你一样惊讶……

答案2

通过移动 Docker 端口并创建socat代理解决了此问题systemd,具体方法如下此 GitHub 讨论.步骤如下:

移动容器的端口,8080:80例如8443:443

安装索卡特

apt-get install socat

创建两个systemd用于socat监听 IPv4 和 IPv6 的服务,并将流量转发到服务的 IPv4 端点:

nano /etc/systemd/system/socat-tcp-80.service

[Unit] 
Description=Socat TCP:80 
After=network.target

[Service] 
Type=simple 
User=root 
ExecStart=/usr/bin/socat TCP6-LISTEN:80,,su=nobody,fork,reuseaddr TCP4:127.0.0.1:8080
Restart=on-failure

[Install] 
WantedBy=multi-user.target

保存该文件并为端口创建另一个文件443

启动服务并在启动时启用它们:

systemctl start socat-tcp-80
systemctl start socat-tcp-443
systemctl enable socat-tcp-80
systemctl enable socat-tcp-443

您可以使用它journalctl -feu socat-tcp-80来获取您的服务的日志。

我不知道为什么 docker 的行为最近发生了变化,但是这种解决方法仍然允许我们支持 IPv6。

相关内容