CentOS 7 yum源404修复与Docker安装指南
如果你手头还有一台 CentOS 7大概率在某次yum操作时撞到过这种画面命令行先卡在 Loading mirror speeds接着冒出一串Could not resolve host、HTTP Error 404 - Not Found最后以[Errno 14]收尾。别急着怀疑网络也别急着重装系统这多半是 yum 源文件里的官方地址已经失效了。这篇内容以我实际维护的一台 CentOS 7 老机器为线索从源故障的定位与换源讲起一直到 Docker 环境顺利装好并调好关键运行参数所有命令都能直接复制执行重点把最容易踩坑的源文件处理、GPG 校验和依赖冲突单独拿出来说明。1. 故障定位先搞清是网络问题还是 yum 源本身废了1.1 yum 报错现场的几种典型表现我这次遇到的第一反应是执行yum makecache结果输出比平时长很多一直停在Determining fastest mirrors然后刷出类似内容http://mirror.centos.org/centos/7/os/x86_64/repodata/repomd.xml: [Errno 14] HTTP Error 404 - Not Found又或者直接这样Could not resolve host: mirrorlist.centos.org; 未知的错误还有一种隐蔽情况是安装了第三方扩展源比如某个 EPEL 扩展源文件里写着旧地址yum install安装任何包时都会因为Cannot retrieve metalink for repository直接中断。单看报错特别像 DNS 故障因为curl解析不了域名但实际上换个yum源就能解决一大半问题。判断故障范围有一个笨办法先把yum换源动作放一边手动访问一下报错里出现的域名。比如curl -I http://mirrorlist.centos.org如果返回 404 或者超时基本可以确定是本机之外的仓库端问题如果连域名解析都对不上再查/etc/resolv.conf和网络连通性。网络修完发现 yum 还是报同样错误那基本就坐实了是本地源配置太老。1.2 为什么 CentOS 7 的默认源会集体失效CentOS 7 进入维护停止阶段后官方把历史版本的软件包全部转移到了归档目录之前常规使用的mirrorlist.centos.org和mirror.centos.org路径不再继续同步。也就是说服务器上原有/etc/yum.repos.d/CentOS-Base.repo里指向的这些地址虽然配置文件还在但远端目录已经不存在了结果必然是一大串 404。另一个更容易被忽略的点是公共镜像站的上游同步策略。很多镜像站点会逐步清退已经停止维护的发行版目录就算你的仓库文件指向的是某个公共镜像路径镜像站上游一旦不再同步 CentOS 7本地执行yum clean all yum makecache依然会失败。所以不要把希望寄托在“旧地址还能用”上正确做法是主动切换到归档源或仍然提供 7 版本的镜像站。以前我们不常碰这种问题是因为源文件会随着发行版更新一起换掉。但 CentOS 7 已经不再有常规更新源文件自然就停留在老状态。换句话说这台机器自己不会好必须手动干预。1.3 动手换源前先做三个确认换源之前我建议按下面顺序操作能省下不少后面排查的时间。第一确认本机网络。不要用ping很多环境禁 ICMP最好用 curl 访问一个稳定页面比如curl -I https://www.centos.org能拿到 HTTP 响应头说明网络没问题。第二查看/etc/yum.repos.d/目录里到底有哪些源文件用ls -l /etc/yum.repos.d/把官方源和第三方源分清楚别一股脑全禁用。第三检查系统时间date -R看一眼如果系统时间偏差太大HTTPS 请求会因为证书校验失败出现各种奇异报错很多人忽略这一项。2. 恢复 yum 源备份、换源、清理缓存一条龙2.1 动手前先备份而不是直接删配置我见过有人直接rm -rf /etc/yum.repos.d/*.repo然后从网上复制新配置。这个方法能用但最大的问题是不可回滚而且如果新配置写错连排查的参照物都没了。更稳的做法是先把旧配置挪走mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/备份后ls /etc/yum.repos.d/应该是空的后续所有的.repo文件都是我们自己创建的降低混乱程度。这里多说一句如果只是某个第三方源失效但官方源还能用不要连官方源一起备份迁移。尽量只禁用出问题的源把影响面控制在最小范围。老机器上跑的存量服务没人知道依赖什么多动一次手就多一分风险。2.2 生成新的源文件指向归档源或可用镜像对于 CentOS 7最稳的基础源是官方归档地址vault.centos.org。我在/etc/yum.repos.d/下新建了CentOS-Base.repo内容如下[base] nameCentOS-7 - Base - vault baseurlhttps://vault.centos.org/7.9.2009/os/x86_64/ gpgcheck1 gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 enabled1 [updates] nameCentOS-7 - Updates - vault baseurlhttps://vault.centos.org/7.9.2009/updates/x86_64/ gpgcheck1 gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 enabled1 [extras] nameCentOS-7 - Extras - vault baseurlhttps://vault.centos.org/7.9.2009/extras/x86_64/ gpgcheck1 gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 enabled1注意我写的是7.9.2009而不是$releasever。原因很简单$releasever在 CentOS 7 上会解析成7但归档目录的真实结构里更多能看到7.9.2009这种具体版本号。虽然部分路径做了软链但为了减少不确定性直接把版本写死更省心。如果你所在网络访问vault.centos.org速度不理想可以把baseurl换成你实测可用的公共镜像站地址。绝大多数镜像站保留的路径格式是https://镜像站基础路径/centos/7/os/x86_64/注意确认一下该镜像站是否还同步 CentOS 7。至于具体选哪家我的建议是去镜像站帮助页看同步状态不要听别人说可以用就直接写上去否则还是会遇到 404。2.3 处理 GPG 密钥这步不能图省事跳过很多人换了源以后跑yum install会在末尾看到GPG key retrieval failed或者Public key for xxx.rpm is not installed。这是因为新源启用了gpgcheck1但本机没有导入对应的签名公钥。CentOS 7 的官方公钥通常已经躺在/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7里。如果系统没导入手动导入一下rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7个别情况下镜像站使用的是自己签发的密钥那需要在源文件的gpgkey字段里写镜像站提供的密钥地址。这里千万注意不要遇到密钥错误就把gpgcheck0关闭。老环境最怕依赖包被替换开启 GPG 校验至少能挡住一层低级风险。清缓存并验证源状态yum clean all yum makecache yum repolist如果makecache正常结束能看到 base、updates、extras 三个仓库的元数据下载成功这一阶段就算过关了。我个人习惯再做一次yum install -y yum-utils因为后面配置 Docker 源时要用到yum-config-manager提前装好省得来回折腾。3. 安装 Docker源正确了依赖问题也少一大半3.1 安装前先看一眼系统底子Docker 在 CentOS 7 上能跑但先要确认内核符合条件。执行uname -rCentOS 7 默认内核一般是 3.10.xDocker 官方也是按这个内核做兼容。基础容器运行没问题但如果以后要跑比较新的镜像建议评估是否升级内核。老服务器生产环境我一般不轻易升级内核除非有明确需求比如要用到更新内核模块或新特性。还要看下内核是否加载了相关网络模块避免后面 iptables 报错。至少确认/proc/net/ip_tables_names存在或者lsmod | grep -E iptable_nat|ip_tables如果输出为空可能需要先加载模块。更常见的坑是安装完 Docker 启动时报 iptables 相关的 NAT 失败这时候检查系统是否启用了 firewalld或者 iptables 服务是否被 disable。测试环境可以临时systemctl stop firewalld但生产环境要谨慎因为停下来会影响防火墙规则。3.2 添加 Docker 仓库并解决 404 问题CentOS 7 上安装 Docker我不建议用发行版自带的旧版本 Docker 包而是用 Docker 官方仓库或可信镜像仓库。官方仓库地址是yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repoyum-config-manager来自yum-utils前面如果已经装好了这里就能直接用。它会生成一个/etc/yum.repos.d/docker-ce.repo文件里面包含 stable、test、nightly 等仓库源默认启用的通常是 stable。如果download.docker.com访问不了或者你觉得速度太慢可以把仓库文件里的 baseurl 改成自己可达的镜像路径。具体做法是生成文件后执行sed -i s#download.docker.com#你选定的镜像地址#g /etc/yum.repos.d/docker-ce.repo注意这个替换会把多个字段一起改动改完后仔细看一眼docker-ce.repo确认路径格式是linux/centos/7/x86_64/stable别把多级路径拼错。我实际遇到过一次镜像站路径缺了linux一级导致 yum 报 404排查时看了半天才发现是 URL 结构不一致。添加完成后再做一次yum makecache fast然后直接安装yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin如果只想装最小运行环境docker-ce、docker-ce-cli、containerd.io 三个包就够了。docker-buildx-plugin和docker-compose-plugin属于扩展工具能装就装上后面处理多阶段构建和编排项目会方便很多。3.3 依赖冲突的经典场景container-selinux在较老的 CentOS 7 上执行上面的安装命令时很容易出现类似提示Error: Package: containerd.io-x.x.x requires container-selinux 2.107这是因为 Docker 相关组件依赖较新的container-selinux而系统自带的版本太老且软件源里可能找不到匹配版本。网上有人建议用--skip-broken跳过依赖我强烈不建议这么做跳过依赖会让运行时行为不可控后面容器起不来更麻烦。正确顺序是先在 extras 源里找container-selinuxyum install -y container-selinux如果 extras 源本身已经失效或版本不满足就去归档源里手动找对应 rpm。比如从vault.centos.org/7.9.2009/extras/x86_64/Packages/下找到container-selinux-*.rpm用rpm -Uvh本地安装再重新执行 Docker 安装命令。我处理过的一台机器就是这样前后多了几分钟但整个依赖树是完整的后续没再出问题。安装完成后启动并设置开机自启systemctl start docker systemctl enable docker systemctl status docker如果是刚装好的干净环境systemctl status docker会显示 active (running)。再跑一个docker version能看到 Client 和 Server 的版本信息只要 Server 段不是报 failed to connect说明 Docker 系统服务已经正常。4. 运行时配置别装完就以为万事大吉4.1 daemon.json 里几个值得提前调的参数Docker 装好后默认配置可以直接用但不建议直接用。生产环境常见的磁盘写满、日志爆炸、内核防火墙冲突很多都能通过一个配置文件提前规避。我习惯创建/etc/docker/daemon.json{ registry-mirrors: [https://docker.mirrors.example.com], exec-opts: [native.cgroupdriversystemd], storage-driver: overlay2, log-driver: json-file, log-opts: { max-size: 50m, max-file: 3 } }逐项解释一下registry-mirrors配置镜像加速地址国内网络拉公共镜像会快很多但这里要填你实际可用的加速器或内部仓库地址不要迷信网上随便找的地址。exec-opts里的native.cgroupdriversystemd特别重要尤其当你以后计划在这台机器上跑 Kubernetes 相关组件时。Docker 默认 cgroup 驱动是 cgroupfs而 kubelet 默认用 systemd两者不一致会直接导致节点状态异常。即使现在不用 k8s我也建议一开始就统一成 systemd省得后期改驱动造成存量容器需要重启。storage-driver用 overlay2这是现代 Docker 的默认存储驱动性能和稳定性都优于老的 devicemapper。但要注意如果根文件系统是 XFS 且格式化时没开启ftype1overlay2 会拒绝使用Docker 启动时会报错。遇到这个情况先执行xfs_info / | grep ftype如果输出ftype0说明文件系统不支持 overlay2要么重新格式化分区并显式添加-n ftype1要么临时把 storage-driver 改成vfs。vfs 性能差适合临时测试生产环境要重新规划存储。日志配置也很实用。json-file加max-size和max-file能让单个容器日志最高 50MB、最多保留 3 个文件避免长时间运行的容器把磁盘塞满。之前踩过一次坑一个打印大量日志的服务一天写了十几 GB磁盘直接告警从那以后我新建任何 docker 环境都会带上这个配置。4.2 重启并验证配置生效配置写到/etc/docker/daemon.json后要重启 Docker 才会生效systemctl restart docker docker info重点看输出里的几行Cgroup Driver是不是 systemdStorage Driver是不是 overlay2Registry Mirrors里有没有你配置的地址。如果显示Cgroup Driver: cgroupfs说明 daemon.json 里exec-opts写的位置不对或者 JSON 格式有问题重启不会报错但配置也没加载。检查 JSON 可以用python -m json.tool /etc/docker/daemon.json这个命令专门用来校验 JSON 语法命令行只报你能看懂的错误。我见过有人少写一个逗号或引号系统不会主动告诉你最后发现配置没生效才回头查这里。Docker 配置验证好以后跑一个最小化容器确认链路完整docker run --rm hello-world docker ps -ahello-world是个极小的镜像能成功下载并退出说明 pull、run、容器运行时这几条链路都正常。如果pull阶段就超时优先检查registry-mirrors地址是否可用再查 DNS 和相关防火墙。5. 常见问题与排查技巧实录5.1 高频报错速查表报错现象常见原因解决办法Could not resolve host: mirrorlist.centos.org官方源域名不再提供解析或 DNS 异常换 vault 源或可用镜像站HTTP Error 404 - Not Foundduring makecache源路径已归档 / 镜像站清退大版本用 7.9.2009 明确版本路径GPG key retrieval failed公钥未导入或 gpgkey 地址不可达rpm --import对应公钥文件Package docker-ce is not availableDocker 仓库文件未生效检查/etc/yum.repos.d/docker-ce.repocontainer-selinux 2.107requiredextras 源里没有匹配依赖单独安装 container-selinux 后重试Failed to create NAT chainon docker startiptables 或 firewalld 异常确认内核模块、临时停 firewalld 测试docker.sock: connect: permission denied当前用户不在 docker 组把用户加入 docker 组或使用 sudooverlay2 文件系统不支持XFS 未开启 ftype1xfs_info查看重新格式化或换 vfs这张表基本是我这几年在老机器上维护环境时整理出来的高频问题。看报错不要只看最后一行要往前面翻yum的输出里往往已经给出了失败的具体 repo 路径。5.2 几个实用但容易忽略的小技巧第一保留旧源配置文件备份的好处不只是回滚。当系统真正要迁移或重装时备份里能看出原来装过哪些第三方源这对排查历史依赖很有参考价值。所以备份目录我通常保留一段时间不会修完源就马上清理。第二遇到yum下载缓慢或无响应可以考虑给/etc/yum.conf里加超时参数timeout30这个参数控制每个请求的超时时间默认值往往是很长网络不佳时很容易卡死。调短以后失败会快速返回至少能立刻知道是哪个源出问题。第三如果 Docker 服务突然挂掉不要急着重启先看日志journalctl -u docker --no-pager -n 50很多启动失败的原因记录在这里。最常见的是 daemon.json 配置错误、磁盘空间不足、iptables 规则加载失败。日志里会把具体错误路径或配置项名写出来比自己翻配置快很多。第四关于镜像加速地址建议你实际测试再写入 daemon.json。有的加速地址只是临时有效过了段时间就返回 401 或超时。换个思路如果你有一台带宽好的内网服务器可以部署一个轻量级镜像仓库作为私有 registry把常用镜像缓存进去稳定性反而更高。这一步扩展性很强后续不管做 CI 还是部署都能复用。个人在处理这类老环境时最大的感受是先备份再验证每个阶段用命令确认结果不要一口气把所有配置全改完再回头看。源故障不要动不动就重装系统因为你不知道系统上跑了多少个存量依赖把源和依赖修好后面装 Docker 就是水到渠成的事。这套思路不仅适用于当前这台 CentOS 7遇到其他进入维护停止期的发行版一样能派上用场。