• 微信
    咨询
    微信在线咨询 服务时间:9:00-18:00
    纵横数据官方微信 使用微信扫一扫
    马上在线沟通
  • 业务
    咨询

    QQ在线咨询 服务时间:9:00-18:00

    选择下列产品马上在线沟通

    纵横售前-老古
    QQ:519082853 售前电话:18950029581
    纵横售前-江夏
    QQ:576791973 售前电话:19906048602
    纵横售前-小李
    QQ:3494196421 售前电话:19906048601
    纵横售前-小智
    QQ:2732502176 售前电话:17750597339
    纵横售前-燕子
    QQ:609863413 售前电话:17750597993
    纵横值班售后
    QQ:407474592 售后电话:18950029502
    纵横财务
    QQ:568149701 售后电话:18965139141

    售前咨询热线:

    400-188-6560

    业务姚经理:18950029581

  • 关注

    关于纵横数据 更多优惠活动等您来拿!
    纵横数据官方微信 扫一扫关注官方微信
  • 关闭
  • 顶部
  • 您所在的位置 : 首页 > 新闻公告 > 云服务器镜像拉取失败原因?

    云服务器镜像拉取失败原因?

    说实话,每次在云服务器上执行docker pull的时候,我心里都会绷着一根弦。不是因为别的,而是镜像拉取失败这件事,我遇到的次数实在太多了。有时候是超时,有时候是找不到镜像,有时候是权限报错,还有时候是拉到了一半卡住不动了。那种感觉就像你在网上下载一个很大的文件,眼看着进度条走到百分之九十,突然报错说下载失败,真的是又气又无奈。

    这篇文章我想把这些年遇到的镜像拉取失败的案例和原因,系统地整理一下。希望能帮你少踩一些坑。

    网络不通:最让人头疼的罪魁祸首

    先从最常见的说起。镜像拉取失败,十有八九是网络问题。我记得有一次,在一台国内某云厂商的服务器上执行docker pull,命令敲下去之后就开始了漫长的等待。过了快两分钟,屏幕上弹出一行错误信息:“net/http: request canceled while waiting for connection”。这个报错的意思很直白,Docker客户端在等待服务器响应的时候超时了。

    我当时的第一反应是检查这台服务器能不能访问外网。用curl试了一下百度的首页,能正常返回内容。再试了一下谷歌的首页,卡住了。问题找到了,这台服务器可以访问国内网站,但访问国外网站的线路不稳定甚至完全不通。而Docker Hub的服务器在国外,自然也就连不上了。

    解决这种问题的思路其实不复杂。一个办法是给Docker配置镜像加速器。国内很多云厂商都提供了免费的镜像加速服务,比如阿里云、腾讯云、华为云都有自己的镜像仓库,可以作为Docker Hub的代理。配置方法是在/etc/docker/daemon.json文件里加上registry-mirrors这一项,把加速器的地址写进去。修改完之后重启Docker服务,再拉取镜像就会发现速度快了很多,而且基本不会超时了。

    另外一个办法是给Docker配置代理。如果你的云服务器本身可以通过代理访问外网,可以让Docker也走这个代理。配置方法是在/etc/systemd/system/docker.service.d/目录下创建一个配置文件,写入HTTP_PROXY和HTTPS_PROXY环境变量。配置完成之后重载systemd配置并重启Docker,镜像拉取就会走代理通道了。不过需要注意一点,如果代理服务器关掉了或者网络断了,Docker还会尝试走代理,反而会导致拉取失败,所以用完代理之后记得把配置清理掉。

    还有一个容易被忽略的网络问题是DNS解析失败。有时候你ping一个域名能通,但docker pull就是报错,报错信息里可能会包含“DNS lookup failed”或者“could not resolve host”这样的关键词。这种情况通常是Docker使用的DNS服务器配置有问题。解决方案是在daemon.json里指定一个可用的DNS服务器,比如114.114.114.114或者云厂商内网的DNS地址。另外,云主机的/etc/resolv.conf文件也需要检查一下,确保里面有可用的nameserver配置。

    镜像地址错误:一个字母的差别

    这个问题听起来有点低级,但真的很容易犯。我有一位同事,从文档里复制了一个镜像地址,结果拉取的时候一直报“not found”。他检查了镜像仓库,确认这个镜像确实存在。后来我发现,他复制的时候多复制了一个空格,导致镜像地址变成了“nginx :latest”,中间多了一个空格。Docker把这个带空格的字符串当成完整的镜像名称去拉取,自然找不到。

    镜像地址错误的类型还挺多的。最常见的是标签写错了,比如镜像的版本号是1.21,你写成了1.2.1。还有时候是仓库地址写错了,比如把docker.io写成了docker.com。另外有一种情况比较隐蔽,就是镜像名称的大小写问题。Docker Hub上的镜像名称是区分大小写的,ubuntu和Ubuntu指向的是两个完全不同的镜像。

    如果是在云厂商的容器镜像服务里使用私有镜像,还需要特别注意镜像地址的格式。通常完整的镜像地址包含仓库域名、命名空间、镜像名称和标签四部分。任何一个部分写错了,拉取都会失败。我自己的习惯是,从控制台直接复制镜像的“下载指令”,而不是手打,这样可以避免很多拼写错误。

    权限问题:私有镜像的拦路虎

    拉取公有镜像一般不需要认证,但拉取私有镜像就不一样了。如果你在云厂商的容器镜像服务里上传了一个私有镜像,直接docker pull是会报错的,错误信息通常是“unauthorized: authentication required”或者“denied: requested access to the resource is denied”。

    这个问题解决起来也不复杂。先用docker login命令登录到镜像仓库,输入用户名和密码。登录成功之后,Docker会把认证信息保存在本地,后续的拉取操作就会带上这个认证信息。

    但在Kubernetes环境里就不太一样了。Kubelet拉取镜像的时候,不会使用你本地docker login的认证信息。这时候需要创建一个imagePullSecret,把这个密钥配置在Pod的spec里。如果没有配置这个密钥,kubelet去拉取私有镜像的时候没有权限,Pod就会一直处于ImagePullBackOff状态。

    另外还有一个权限相关的问题是,使用云厂商的镜像服务时,当前账号有没有下载镜像的权限。如果是子账号或者IAM用户,需要在主账号的容器镜像服务里给这个用户授权,否则即使登录成功了,拉取镜像的时候也会报权限不足。

    磁盘空间不足:下载了却存不下

    镜像拉取失败还有一个不太起眼但很常见的原因,就是磁盘空间不够了。Docker拉取镜像的时候,会把镜像的每一层都下载到本地,然后解压存储。如果/var/lib/docker目录所在的磁盘分区已经满了,拉取过程就会在最后一步失败,报错信息里会出现“no space left on device”这样的字样。

    我遇到过一台云服务器,上面跑了十几个容器,日志文件把磁盘占满了。执行docker pull的时候,镜像下载到一半就报错了,说没有空间写入文件。解决方法是先清理一下磁盘空间。docker system prune命令可以一键清理那些没有被使用的镜像、容器、卷和网络,释放出不少空间。如果不想清理所有东西,也可以用docker image prune只清理多余的镜像,或者用docker container prune只清理已经停止的容器。

    还有一个比较彻底的办法是给Docker的数据目录扩容。如果/var/lib/docker是独立的分区,可以考虑增加这个分区的大小。如果不是独立分区,可以把Docker的数据目录迁移到一个空间更大的磁盘上,修改daemon.json里的data-root配置项,然后重启Docker。

    镜像本身的问题:版本太低或者文件损坏

    有时候问题不在你的环境,而在镜像本身。我遇到过一种情况,拉取一个旧版本的镜像,Docker报了一个很奇怪的错误:“failed to unpack image on snapshotter: failed to get reader from content store”。查了很久才发现,这个镜像是用很老版本的Docker打包的,当时的镜像格式标准和现在的Docker不兼容。解决方案是找一个新版本打包的镜像来替代,或者放弃使用这个镜像。

    还有一种情况是镜像文件在传输过程中损坏了。Docker拉取镜像的时候会对每一层进行校验,如果校验和不匹配,就会报“checksum mismatch”或者“corrupt layer”的错误。这种问题比较少见,通常发生在网络不稳定的环境下,数据包在传输过程中出现了错误。解决方法是重新拉取一次,如果还是同样的问题,可能是镜像仓库里的文件本身就有问题,需要联系镜像的维护者。

    容器引擎异常:有时候重启就好了

    最后说一个比较玄学的情况。有时候Docker本身出了问题,导致镜像拉取失败。我之前遇到过一台云服务器,之前拉取镜像都正常,突然有一天就不行了。检查了网络、DNS、磁盘空间,都没发现问题。最后试着重启了一下Docker服务,systemctl restart docker,然后再拉取镜像就正常了。

    这种“重启就好了”的问题,通常是因为Docker守护进程内部状态出现了异常,比如某个线程卡住了、某个锁没有释放、或者缓存数据出了问题。重启之后一切从头开始,问题自然就消失了。虽然不够优雅,但在紧急情况下是一个很有效的临时解决方案。

    如果重启还不行,可能是Docker的版本太老了。新版本的Docker修复了很多旧版本的bug,也支持更多的特性。可以考虑升级一下Docker的版本,看看问题是否得到解决。

    总结

    写到这里,回头看看这些年遇到的镜像拉取失败的问题,我发现一个规律:大部分问题的根源都指向了一个方向——环境。

    云服务器的网络环境和本地不一样,限制更多,延迟更高,访问国外服务不稳定。云服务器的存储资源配置也和本地不同,磁盘空间有限,需要定期清理。云服务器的安全策略更严格,端口和流量的管控更细致。

    而镜像拉取这件事,恰恰对网络、存储、权限这三个方面都有要求。任何一个环节出了问题,拉取就会失败。

    我的经验是,遇到镜像拉取失败,按照这个顺序来排查。先看网络,能不能访问外网,能不能解析镜像仓库的域名。再看配置,镜像加速器配了没有,代理配了没有。接着看权限,拉取的镜像是不是私有的,需不需要登录。然后看资源,磁盘空间够不够。最后看镜像本身,地址对不对,标签对不对。



    最新推荐


    微信公众帐号
    关注我们的微信