关于Docker 无法连接到 Docker Hub 和镜像加速器的问题
今天遇到一个比较常见的问题,虽然尝试了很多办法仍然没有解决(因为通过咨询问题出在云主机那边,只能等那边解决),但是总结出了涉及多个方面,包括 DNS 配置、网络连通性、防火墙设置等所有步骤和测试方案。
问题描述
当我们尝试拉取 alpine
镜像时,收到如下错误信息:
Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
同时,使用 curl
测试直接访问 Docker Hub 的 HTTPS 端点也失败了:
curl -v https://registry-1.docker.io/v2/
输出显示 Connection refused
和 Network is unreachable
错误。
诊断过程
1. 检查 DNS 配置
首先,检查当前配置的 DNS 服务器是否能够解析所需的域名。使用 nslookup
命令测试:
nslookup registry-1.docker.io
结果表明:当前配置的 DNS 服务器无法解析部分国内镜像加速器的域名,但可以解析 registry-1.docker.io
。
2. 更换 DNS 服务器
修改系统的 DNS 设置可以帮助解决由于 DNS 解析问题导致的网络连接问题。在 Linux 系统上,你可以通过修改 /etc/resolv.conf
文件来更改 DNS 服务器地址。然而,在许多现代 Linux 发行版中,直接编辑 /etc/resolv.conf
可能不会生效,因为该文件可能由系统服务(如 NetworkManager
或 systemd-resolved
)管理。
以下是几种常见的修改 DNS 设置的方法:
方法 1:直接编辑 /etc/resolv.conf
这种方法适用于那些不使用 NetworkManager
或 systemd-resolved
的系统。请注意,如果你的系统使用这些服务,直接编辑 /etc/resolv.conf
可能会在重启后被覆盖。
-
使用文本编辑器打开
/etc/resolv.conf
文件:sudo nano /etc/resolv.conf
-
添加或修改 DNS 服务器地址。例如,添加 Google 的公共 DNS 服务器:
nameserver 8.8.8.8 nameserver 8.8.4.4
-
保存并关闭文件。
方法 2:通过 NetworkManager
修改
如果系统使用 NetworkManager
,可以通过以下步骤修改 DNS 设置:
-
打开终端并列出所有网络接口:
nmcli device show
-
找到你要配置的网络接口名称(例如
eth0
),然后使用以下命令设置 DNS:sudo nmcli con modify "你的连接名称" ipv4.dns "8.8.8.8 8.8.4.4" sudo nmcli con modify "你的连接名称" ipv4.ignore-auto-dns yes sudo nmcli con up "你的连接名称"
其中
"你的连接名称"
是你从nmcli connection show
命令输出中找到的网络连接名称。
方法 3:通过 systemd-resolved
修改
如果系统使用 systemd-resolved
,可以通过编辑 /etc/systemd/resolved.conf
文件来设置全局 DNS:
-
编辑
/etc/systemd/resolved.conf
文件:sudo nano /etc/systemd/resolved.conf
-
找到
[Resolve]
部分,并添加或修改以下行:[Resolve] DNS=8.8.8.8 8.8.4.4
-
保存并关闭文件。
-
重启
systemd-resolved
服务以应用更改:sudo systemctl restart systemd-resolved
-
如果你的系统仍然使用
/etc/resolv.conf
,你可能需要将其链接到systemd-resolved
提供的 stub 文件:sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
方法 4:对于 Docker 守护进程单独设置 DNS
如果你想只为 Docker 容器设置 DNS 服务器,可以在 Docker 的配置文件 /etc/docker/daemon.json
中进行配置:
-
编辑或创建
/etc/docker/daemon.json
文件:sudo nano /etc/docker/daemon.json
-
添加或修改以下内容:
{ "dns": ["8.8.8.8", "8.8.4.4"] }
-
保存并关闭文件。
-
重新加载 Docker 守护进程以应用更改:
sudo systemctl daemon-reload sudo systemctl restart docker
通过以上方法之一,你应该能够成功地修改系统的 DNS 设置。选择最适合你系统配置的方法进行操作即可
3. 测试新的 DNS 配置
确认新的 DNS 配置是否生效,并且能够解析所需的域名:
nslookup registry-1.docker.io
如果这些命令返回有效的 IP 地址,则说明 DNS 配置正确。使用解析出来的 IP 地址进行测试:
curl -v https://:443/v2/
如果直接使用 IP 地址仍然无法连接,可能是目标服务器对某些 IP 范围有访问限制,或者该服务暂时不可用。
4. 再检查网络连通性
使用 telnet
或 nc
命令测试端口连通性:
telnet registry-1.docker.io 443
# 或者
nc -zv registry-1.docker.io 443
如果这些命令显示无法连接或超时,可能是因为防火墙或其他网络安全设置阻止了出站 HTTPS 请求,而不仅仅是与 Docker Hub 的连接问题。
5. 使用阿里云镜像加速器
如果 DNS 和基本网络连通性都没有问题,但仍无法通过 Docker Hub 下载镜像,建议直接使用阿里云的镜像加速器来拉取镜像:
docker pull registry.cn-hangzhou.aliyuncs.com/library/alpine:latest
6. 检查防火墙和安全组规则
最后,确保主机上的防火墙规则以及云服务提供商的安全组设置允许出站 HTTPS 流量(端口 443)。查看主机上的 iptables 规则:
sudo iptables -L -n | grep 443
同时,登录到云控制台,检查与你的实例相关联的安全组规则,确保允许出站 HTTPS 流量。
总结
通过逐步排查 DNS 配置、网络连通性和防火墙设置,可以排除一些 Docker 容器无法连接到 Docker Hub 或镜像加速器的问题。以下是关键步骤:
- 检查并更换 DNS 服务器:确保能够解析所有必要的域名。
- 测试网络连通性:确认可以建立到 Docker Hub 的 HTTPS 连接。
- 使用镜像加速器:尝试使用国内的镜像加速器下载镜像。
- 检查防火墙和安全组规则:确保没有阻止出站 HTTPS 请求。
这篇博客内容只是个人尝试和总结,若有不足和错误之处请指出。见谅!