内网环境自建本地YUM仓库实战:从挂载ISO到createrepo全流程

发布时间:2026/10/15 7:23:39
内网环境自建本地YUM仓库实战:从挂载ISO到createrepo全流程 1. 为什么内网环境必须自建本地 YUM 仓库很多刚接触企业内网运维的朋友都会遇到一个很尴尬的场景服务器集群全部跑在隔离网络里没有任何外网出口结果装个nginx或者gcc都装不上yum install一敲下去就是满屏的Could not resolve host或者Cannot find a valid baseurl。这时候本地 YUM 仓库就是救命稻草。所谓本地 YUM 仓库本质上是把一堆 RPM 包按照 YUM 能识别的目录结构组织起来再通过file://、http://或ftp://的方式暴露给客户端让yum命令能够像访问公网源一样去解析依赖、下载安装。它解决的核心问题有三个第一是断网环境下的软件安装与依赖解析第二是批量部署时避免每台机器重复下载第三是版本锁定保证整个集群装的都是同一批经过测试的包不会因为公网源更新导致环境漂移。这套方案适合谁我总结下来主要是三类人一是负责内网服务器交付的运维工程师二是做离线交付项目的实施人员三是在实验室或教学环境里需要统一软件版本的技术负责人。哪怕你只是想在虚拟机上练手把本地源配一遍对理解 YUM 的工作机制也特别有帮助因为你会被迫去看repodata目录里到底放了什么。我见过太多人卡在“光盘挂载了但 yum 还是报错”这一步其实问题往往不在挂载而在于repo文件里的baseurl路径写错、gpgcheck没关、或者createrepo没跑。下面我就按实际交付的顺序把整套流程拆开讲透包括每一步为什么这么做、参数怎么算、坑在哪里。2. 本地 YUM 仓库的两种主流形态与选型思路2.1 光盘镜像源与目录聚合源的差异本地 YUM 仓库落地时实际只有两种常见形态选错了后面会反复返工。第一种是光盘镜像源直接拿系统安装 ISO 挂载把BaseOS、AppStream这些目录当成源。它的优点是零成本、包经过官方签名、开箱即用缺点是包版本固定ISO 里没有的第三方包比如某些中间件、监控 agent就装不了而且 ISO 一旦更新路径可能变化。第二种是目录聚合源自己建一个目录把从各处收集来的 RPM 全丢进去用createrepo生成元数据。它的优点是包可以自由增删、能混入第三方包、方便做版本管理缺点是需要自己维护依赖完整性包缺依赖时createrepo不会报错但客户端安装时会失败。我的选型建议很直接如果只是给内网机器装系统自带软件用光盘镜像源就够了如果要做离线交付、需要装一堆非官方包必须上目录聚合源而且最好两者并存——光盘源作为基础聚合源作为补充通过priority或exclude控制优先级。2.2 服务端与客户端角色划分不管哪种形态角色划分都是一样的一台机器做服务端存放 RPM 和 repodata其余机器做客户端配置 repo 文件指向服务端。服务端可以是物理机、虚拟机甚至就是某台客户机自己——如果只有一台机器那就本机挂载本机用baseurl写file://即可。这里有个容易忽略的点服务端如果通过 HTTP 提供服务需要装httpd或nginx如果只是本机或通过共享目录访问file://最省事。我在内网批量交付时通常选 HTTP因为客户端配置统一不用每台机器都挂载 ISO维护成本最低。提示服务端和客户端的系统大版本必须一致比如都是 8 系列或都是 7 系列。跨大版本混用 RPM 会出现 glibc 依赖冲突这个坑非常深后面排查章节会细说。3. 服务端实操从挂载镜像到生成 repodata3.1 挂载 ISO 与目录规划先确认 ISO 文件位置假设放在/opt/iso/下。创建挂载点并挂载mkdir -p /mnt/cdrom mount -o loop /opt/iso/system.iso /mnt/cdrom挂载完先ls /mnt/cdrom看一眼正常应该能看到BaseOS、AppStream、EFI等目录。如果只看到Packages和repodata说明是老版本结构路径要相应调整。接下来规划仓库根目录。我习惯用/var/www/html/repo/作为 HTTP 服务的根这样httpd起来后直接就能访问。把 ISO 内容复制进去而不是直接挂载使用原因是挂载点重启会失效复制一份更稳mkdir -p /var/www/html/repo/base cp -r /mnt/cdrom/BaseOS/* /var/www/html/repo/base/ cp -r /mnt/cdrom/AppStream/* /var/www/html/repo/appstream/复制大 ISO 时用cp -r会比较慢可以加-a保留权限或者用rsync -av带进度。这一步的磁盘占用要提前算一个完整 ISO 大概 8~10GB复制两份就是 20GB 左右df -h先确认空间够。3.2 用 createrepo 生成元数据如果只是复制 ISO 内容repodata目录是现成的可以跳过这步。但如果是自己聚合的 RPM 目录必须跑createrepoyum install -y createrepo_c createrepo_c /var/www/html/repo/custom/createrepo_c是 C 版本比老的 Python 版createrepo快很多大目录下差距能到几倍。执行完会在目标目录下生成repodata/文件夹里面有repomd.xml和若干压缩的索引文件。这里有个关键细节每次往目录里增删 RPM 后都要重新跑一次createrepo_c --update否则客户端看不到新包。--update只更新变化部分比全量重建快。我踩过的坑是加完包忘了更新客户端yum clean all后还是找不到排查半天才发现是元数据没刷新。3.3 启动 HTTP 服务并验证yum install -y httpd systemctl enable --now httpd把仓库放在/var/www/html/repo/下浏览器或curl访问http://服务端IP/repo/base/repodata/repomd.xml能返回 XML 内容就说明服务通了。如果返回 403检查 SELinux 和目录权限如果返回 404检查路径拼写。注意SELinux 开启时httpd默认只能读/var/www/html下的文件自定义目录需要chcon -R -t httpd_sys_content_t /var/www/html/repo/否则客户端会报 403。这个坑在 CentOS 7/8 上极其常见。4. 客户端配置repo 文件写法与参数详解4.1 repo 文件的标准结构客户端配置的核心就是/etc/yum.repos.d/下的.repo文件。一个最小可用的配置长这样[local-base] nameLocal BaseOS Repository baseurlhttp://192.168.1.100/repo/base/ enabled1 gpgcheck0逐行解释[local-base]是仓库 ID必须唯一不能和系统自带的重复name是描述随便写但建议有意义baseurl指向 repodata 的上一级目录注意结尾斜杠enabled1表示启用gpgcheck0关闭签名校验内网自建源通常关掉否则需要导入 GPG 公钥。如果服务端是本机baseurl写file:///var/www/html/repo/base/注意是三个斜杠。用file://时不需要 HTTP 服务但要求客户端能访问该路径跨机器就不行了。4.2 gpgcheck 与 priority 的取舍gpgcheck关掉省事但安全性下降。如果坚持开启需要把 ISO 里的 RPM-GPG-KEY 文件复制到客户端并导入rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-xxx然后在 repo 文件里写gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-xxx。内网环境我一般建议关掉因为包来源可控开启反而增加维护成本。priority参数需要装yum-plugin-priorities才生效值越小优先级越高。当光盘源和聚合源同时存在且包有重叠时用priority1让光盘源优先避免第三方包覆盖官方包导致依赖混乱。4.3 清理缓存与验证生效配置完必须执行yum clean all yum makecache yum repolistyum repolist会列出所有启用的仓库和包数量。如果本地源没出现检查文件后缀是不是.repo、enabled是不是 1、baseurl能不能curl通。yum makecache失败时通常会给出具体 URL照着 URL 手动curl一下问题基本就定位了。5. 常见报错与排查速查表实际交付中遇到的报错就那么几类我整理成表格方便对照报错信息根本原因解决方式Cannot find a valid baseurlbaseurl 路径错或服务未启动curl 验证 URL检查 httpd 状态repomd.xml: [Errno 14] HTTP Error 403SELinux 或目录权限chcon 改上下文chmod 755repomd.xml not found没跑 createrepo 或路径指向错确认 repodata 目录存在Package xxx requires yyy聚合源缺依赖包补包后 createrepo --updateGPG key retrieval failedgpgcheck1 但没导入公钥关掉 gpgcheck 或导入 keyMetadata file does not match checksum缓存脏了yum clean all 后重试排查顺序我固定为先 curl 服务端 URL再 yum repolist最后看具体包依赖。90% 的问题在第一步就能暴露。实操心得yum clean all之后一定要yum makecache只 clean 不 makecache 有时会用旧缓存导致改了 repo 文件却不生效这个坑我踩过不止一次。6. 批量交付场景下的自动化与版本管理6.1 用脚本一键部署客户端内网几十台机器手动配 repo 文件不现实写个脚本分发#!/bin/bash REPO_URLhttp://192.168.1.100/repo cat /etc/yum.repos.d/local.repo EOF [local-base] nameLocal Base baseurl${REPO_URL}/base/ enabled1 gpgcheck0 EOF yum clean all yum makecache配合ansible或pssh批量执行几分钟搞定整个集群。脚本里把 URL 抽成变量换环境只改一处。6.2 版本锁定与快照思路本地源最大的价值之一是版本可控。我习惯在聚合源目录里按日期建子目录比如custom/20240115/每次交付前把测试通过的包放进去createrepo后客户端指向这个日期目录。这样即使后续加了新包老环境也不会被影响相当于给依赖做了快照。如果包特别多还可以用reposync从公网源同步到本地再createrepo这样能拿到完整的依赖树。reposync需要外网适合在能联网的跳板机上先同步好再拷贝进内网。7. 我踩过的几个深坑与经验总结第一个坑是跨版本混用。有次图省事把 7 系列的包丢进 8 系列的源里createrepo不报错客户端装的时候 glibc 冲突直接崩。后来我强制规定一个源目录只放同一大版本的包混用必须分目录。第二个坑是软链接失效。为了省空间我用软链接把 ISO 内容链到 web 目录结果httpd默认不跟随软链接客户端 403。解决办法是在httpd.conf里加Options FollowSymLinks或者干脆复制实体文件。第三个坑是createrepo 后忘记更新。前面提过但值得再强调任何 RPM 变动后必须createrepo_c --update否则客户端永远看不到新包而且报错信息很模糊容易误判成网络问题。最后一个经验是保留一份离线应急源。哪怕平时用 HTTP也在每台机器本地留一个最小 ISO 挂载点网络或服务端挂了还能file://应急装包。这个习惯在几次紧急故障里救过场。这套本地 YUM 仓库的方案说到底就是把“依赖解析”这件事从公网搬到内网核心动作就三步准备包、生成元数据、配 repo 文件。把这三步的细节和坑摸透内网软件交付基本就不会再卡壳了。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询