简介面向在国产化服务器环境中部署容器运行时的运维人员与开发者的实操型手册聚焦银河麒麟 V10 SP1 Server 无法直接获取 docker server 软件包这一常见障碍给出可行的版本选择与落地路径。压缩包内共 1 个 docx 文档约 17KB篇幅精炼按配置 yum 源、通过 yum 安装 docker 两大模块编排并附目录便于快速定位章节。文档给出了阿里第三方源与麒麟官方源两份 repo 配置写法并以 docker-ce-cli 18.09.7、docker-ce 18.09.7 的具体安装命令为主线串起服务启动与版本核验环节同时专门记录最新版 docker 因 container-selinux 依赖无法满足而安装失败的报错原文与成因分析帮助读者避开同类问题。目前已有 7220 人学习下载适合需要一份可直接照做的国产系统 docker 部署参照的中级用户。1. 麒麟上装 docker卡在nothing provides container-selinux 2:2.74的那三天在银河麒麟 V10 SP1 Server 上装 docker最常见的失败方式是yum install docker-ce敲下去系统回你一句Error: Problem: cannot install the best candidate for the job - nothing provides container-selinux 2:2.74 needed by docker-ce-3:20.10.17-3.el7.aarch64。搜「docker 银河麒麟」出来的帖子十有八九停在这一步有人加了--skip-broken看着不报错了回头docker --version还是没有命令有人一路--nogpgcheck硬装上去容器起不来、镜像拉不动。这类故障折腾人的地方在于报错只告诉你缺一个包不告诉你缺的是哪个源、哪个版本门槛该退回哪一版。下面把这份安装手册里的实际路径拆开从源配置写到版本选择适合第一次在麒麟服务器上落地容器环境、又不想把系统搞成半残的人。2. 配源这一步docker-ce.repo 少一个斜杠都装不上装不上 docker九成的原因不在 docker 本身在仓库。麒麟服务器默认只挂了自家源yum search docker出来的东西和你想要的不是一回事yum install docker-ce自然也找不到可用的包。所以第一条命令永远是确认仓库而不是直接装。2.1 麒麟官方源里为什么搜不到 docker-ce麒麟 V10 SP1 Server 的官方仓库ks10-os-media这类里容器相关提供的是 podman、skopeo、buildah 这一套docker-ce 不在其中。这不是配置错了是发布策略如此。于是很多人yum search docker之后选了名字里带 docker 的那个包装上去docker命令确实有了docker version输出却和文档对不上docker info里 Server 段要么是 podman 的兼容实现要么干脆报Cannot connect to the Docker daemon。这种“装了个假 docker”的坑比直接报错还费时间。正确做法是两条腿走路docker-ce 本体和它的同族包docker-ce-cli、docker-ce-rootless-extras从 docker 官方的 CentOS 7 仓库拿因为 docker 的 el7 包同时提供 x86_64 和 aarch64 两种架构麒麟的 aarch64 机器能直接用而 container-selinux、libcgroup、libseccomp 这些底层依赖docker 自己的仓库里没有得回到麒麟官方源里解析。两个源同时启用缺一个就会在yum install阶段报依赖缺失。先清理一遍旧缓存很多人改完 repo 文件不makecache看到的还是上一轮的元数据改了半天“没生效”# 清掉旧元数据避免改完 repo 后仍命中旧缓存 yum clean all # 重新拉取所有启用仓库的元数据 yum makecache # 看当前生效的仓库列表确认新加的两个都 enabled yum repolistyum clean all会清掉/var/cache/yum下的元数据和包缓存第一次配置源时必做yum makecache是把各仓库的repomd.xml和 primary 数据拉回本地后面yum list、yum install都基于它yum repolist输出里如果某个仓库显示0个包说明 baseurl 或者网络有问题别急着往下装先把这个仓库修好。2.2 docker-ce.repo 五个字段里最容易写错的是哪个仓库文件放在/etc/yum.repos.d/下文件名随意习惯叫docker-ce.repo。内容按手册给的最小集写[docker-ce-stable] nameDocker CE Stable - 7 # 注意这里写死 centos/7不要用 $releasever baseurlhttps://mirrors.aliyun.com/docker-ce/linux/centos/7/$basearch/stable enabled1 gpgcheck1 gpgkeyhttps://mirrors.aliyun.com/docker-ce/linux/centos/gpg逐字段说清楚因为每个字段都有对应的一种翻车方式。[docker-ce-stable]是仓库 ID后面--enablerepo、--disablerepo都靠这个名字改名之后脚本里的参数要同步改。baseurl里的$basearch由 yum 在运行时替换成机器架构aarch64 机器替换成aarch64x86_64 替换成x86_64所以同一份文件在两种机器上都能用不用手改。真正容易出问题的是路径里的那个7。麒麟 V10 的VERSION_ID是 10如果写成$releaseveryum 会拼出.../linux/centos/10/aarch64/stable这个目录在镜像站上不存在直接 404报错是Failed to download metadata for repo docker-ce-stable或者Cannot download repomd.xml看起来像网络问题实际是路径拼错了。这也是手册里写死7的原因。同理baseurl结尾的斜杠别丢某些 yum 版本在拼接repodata/repomd.xml时不做补斜杠处理少了就变成stable/repodata之外的怪路径。gpgcheck1配合gpgkey是校验包签名用的保证装上的 rpm 没被篡改。gpgkey指向的是 docker 仓库的 GPG 公钥yum 首次安装时会自动下载并导入。这一项如果出问题报错长这样Public key for docker-ce-18.09.7-3.el7.aarch64.rpm is not installed处理办法在后面的避坑章里展开。配完之后先别装用一条只读命令确认仓库里到底有哪些版本可装# 列出所有可见的 docker-ce 版本倒序排列让新版本在上 yum list docker-ce --showduplicates | sort -r--showduplicates是关键参数不加它 yum 只显示每个包的最高版本你会误以为仓库里只有一个 20.10从而以为“只能装最新版”。加上它18.09.7-3.el7、19.03.x、20.10.x 会全部列出来后面的版本选型就有了依据。sort -r只是让输出顺序更符合直觉不影响结果。2.3 麒麟源为什么必须单独加gpgcheck0 能不能忍只用 docker-ce 仓库装不下去因为container-selinux这类包 docker 仓库不提供。麒麟官方源要单独加一个文件按手册的写法[ks10-os-media] name Kylin Linux Advanced Server 10 - Os baseurl http://archive.kylinos.cn/yum/v10/sp1-openstack-q/aarch64/os/ gpgcheck 0 enabled 1写入/etc/yum.repos.d/kylin_aarch64.repo。手册原文这里路径写成了/etc/yum.repos./kylin_aarch64.repo少了个d照着敲的话系统会提示目录不存在或者更坏的情况——你以为写进去了其实文件落在别处yum repolist里根本没有这个仓库。这是纯手误但确实有人卡在这一步很久。baseurl里的aarch64是写死的x86_64 的机器要换成x86_64这个路径不认$basearch。gpgcheck 0意味着不校验这个源的包签名属于妥协做法内网或归档源经常没有正确部署 GPG 公钥开校验会直接卡住依赖安装。判断标准很简单——这个源是你信任的、走内网或官方归档的可以关来源不明的第三方源别为了装上去就关校验。关校验的风险是没有完整性保护属于“能跑但不该长期这样”的状态。两个源都就位后再跑一次yum repolist应该能看到docker-ce-stable和ks10-os-media都在列表里并且包数量不为 0。这一步看着琐碎但它把后面 80% 的报错挡在了门外。3. 报错拆解nothing provides container-selinux 2:2.74到底缺什么3.1 依赖链条docker-ce 不是一个人在战斗yum install docker-ce解析出来的依赖不是一条线是一个小图。docker-ce 依赖 containerd.io容器运行时、docker-ce-cli命令行、container-selinuxSELinux 策略模块、libcgroup、libseccomp、iptables、device-mapper-libs 等等。其中 containerd.io 和 docker-ce-cli 由 docker 仓库自己提供版本能对上container-selinux、libcgroup、iptables 这些由发行版仓库提供也就是麒麟源。报错里的 2:2.74是版本约束2:是 epoch可以理解成版本号的最高优先级字段2.74是版本主体。这句话翻译过来是docker-ce 20.10.17 这个包要求系统里有一个 epoch 为 2、版本不低于 2.74 的 container-selinux而当前启用的所有仓库加起来没有任何一个包能满足这个条件。注意是“没有任何一个包”不是“版本低了装不上”——如果麒麟源里有 2.60yum 的报错会变成requires container-selinux 2:2.74, but 2:2.60 is available之类的形式。所以看到nothing provides第一反应应该是“这个包名在当前仓库里根本不存在”而不是“版本差一点”。验证方法就一条命令# 看麒麟源里到底有没有 container-selinux以及它提供的版本 yum info container-selinux # 如果上面查不到再确认是不是包名不同或被合并进了别的包 yum provides container-selinux 2/dev/null yum search selinux | grep -i containeryum info能查到就说明包在重点看Version和Epoch两行查不到就是彻底没有这种情况在麒麟的精简版仓库里不罕见有些镜像干脆把 SELinux 相关包裁掉了。yum provides是按文件反查包参数给包名本身意义不大但配合2/dev/null可以快速排掉噪音看有没有同名不同源的候选。3.2--nobest和--skip-broken为什么救不了这个错报错末尾那句(try to add --skip-broken to skip uninstallable packages or --nobest to use not only best candidate packages)是 dnf 后端自动附带的建议它坑过不少人。先说清楚麒麟 V10 的yum实际是 dnf 的兼容前端所以输出是Last metadata expiration check这种 dnf 风格这也解释了为什么yum会提示 dnf 的参数。--skip-broken的语义是“遇到装不上的包就跳过把能装的装上”。用在这里docker-ce 正是装不上的那个于是它被跳过yum 退出码是 0看起来成功了。你回头docker --version提示命令不存在或者只装了 docker-ce-cli 没有 daemon。这不是解决问题这是把问题藏起来属于典型的自欺欺人。--nobest的语义是“不要只挑最优最新版本允许退而求其次”。这个参数方向是对的但它有个前提仓库里必须存在一个依赖能被满足的版本。如果仓库里最老的 docker-ce 是 19.03而 19.03 同样要求 container-selinux 2:2.74那--nobest一样失败只是报错信息变长。所以--nobest是“可能有用”不是“一定有用”能不能成得看仓库里有哪些版本。真正有效的做法是反过来先看有哪些版本再逐个确认依赖最后指定版本装。这里有个很实用的技巧是“试运行”只解析不落盘# --assumeno 会在解析完依赖后自动回答 no只输出计划不真的安装 yum install --assumeno docker-ce-18.09.7-3.el7--assumeno会让 yum 把所有需要安装、升级、替换的包列出来然后停下。如果依赖不满足报错在这一步就出现了系统不会被改动。比起真装一次再卸载这个命令安全得多也快得多。把候选版本挨个试一遍哪个能过依赖解析就装哪个。3.3 为什么最终选 18.09.7-3.el7 而不是 20.10手册的结论很明确docker-ce装最新版会失败因为最新版的依赖组件在麒麟系统上无法满足暂时没有找到解决办法所以退回18.09.7-3.el7。这个版本能装上的核心原因是它的依赖门槛更低——老版本对 container-selinux 的最低要求比 20.10 宽松麒麟源里现有的包能过线。选版本时有几个判断依据不只是“能装上就行”。第一是内核兼容性docker 18.09 对内核版本的要求比 20.10 低麒麟 V10 SP1 自带的内核如果是 4.19 系列18.09 跑起来更稳overlay2 存储驱动和 cgroup 的支持不会踩到新版才引入的特性。第二是 CLI 与 daemon 的版本必须一致docker-ce 和 docker-ce-cli 要装同一个版本号混装会出现client version 18.09.7 is too old或者 API 版本不匹配的报错所以两条命令里的版本号要成对改。第三是后续升级路径18.09 是比较老的版本如果业务侧要求 compose v2、buildx 这些新特性迟早要面对升级问题这时候的正确做法是先解决 container-selinux 的来源问题比如从更高版本的发行版仓库里找兼容包或者关掉 SELinux 后不装这个包再升 docker而不是硬升。一个务实的判断顺序先yum list docker-ce --showduplicates | sort -r看有哪些版本从高到低用--assumeno试依赖第一个能过的版本就是你的天花板。这个结论要记下来因为下一次换机器、换麒麟小版本天花板可能变方法不变。4. 按版本装先 cli 后 ce这个顺序不是玄学4.1 为什么手册坚持先装 docker-ce-cli 再装 docker-ce两条命令分开敲看似只是排版习惯实际解决的是“报错信息混在一起看不清”的问题。如果一条命令装两个包yum 会把两个包的依赖合并解析一旦失败你看到的是长长一串Problem:里面既有 cli 的依赖也有 daemon 的依赖很难判断到底是哪个环节断了。分开装之后yum install docker-ce-cli-18.09.7-3.el7这一步只解析 cli 的依赖它依赖的是比较底层的库libc、libseccomp 之类通常能顺利通过通过之后再装docker-ce如果这一步报错你就很确定问题出在 daemon 的依赖上范围一下缩小一半。这不是玄学是把排查变量控制住。尤其是第一次在这台机器上装不确定源配得对不对分开装能最快告诉你“源没问题是版本门槛的问题”。先装 cli 的另一个好处是版本号能先锁死。docker-ce-cli-18.09.7-3.el7装完之后rpm -q docker-ce-cli能看到确切版本后面装 daemon 时照着这个版本号写不会出现“cli 是 18.09、daemon 是 19.03”这种低级的版本错配。4.2 两条安装命令的完整写法和验证动作# 第一步先装命令行客户端锁死版本号 yum install docker-ce-cli-18.09.7-3.el7 # 第二步再装 daemon 本体版本号必须和上面一致 yum install docker-ce-18.09.7-3.el7 # 确认两个包的版本完全对齐 rpm -q docker-ce docker-ce-cli containerd.io命令里的18.09.7-3.el7是完整的 NEVRA 里的版本段格式是主版本.次版本.修订号-打包号.el7.el7表示这是给 RHEL 7 系打的包麒麟 V10 兼容这个 ABI所以能装。版本号写全的好处是 yum 不会自作主张挑最新版装出来的东西和你验过的完全一致可复现。生产环境建议一直这么写别用yum install docker-ce这种不带版本的形式否则哪天仓库更新了同一份脚本在不同时间跑出不同结果。rpm -q那一条是验证动作输出三行版本应该都是18.09.7-3.el7containerd.io 的版本号体系不一样不用强求一致。如果docker-ce-cli显示not installed说明第一步没成或者被第二步的某个obsoletes换掉了这时候别急着往下走回头查。装完之后还有一个容易漏的动作确认 SELinux 状态。如果系统开了 enforcing而 container-selinux 版本又刚好卡在边缘容器启动时会报permission denied却看不出原因。查一下getenforce # 输出 Enforcing 表示强制模式Permissive 表示只记录不拦截这一步不是让你马上去关 SELinux而是留个记录如果后面容器起不来且日志里全是avc: denied那就是它。关掉是应急手段正确的做法是装对应的策略模块但麒麟环境下这个包不好弄很多团队的做法是把 SELinux 调成 permissive 并记进变更单。取舍自己判断。4.3 启动、自启和第一次拉镜像# 启动服务 systemctl start docker # 设为开机自启服务器重启后容器能自己回来 systemctl enable docker # 看守护进程状态Active: active (running) 才算成功 systemctl status docker --no-pager # 验证版本 docker --version # 期望输出Docker version 18.09.7, build 2d0083dsystemctl start docker如果失败systemctl status只会给你一句Job for docker.service failed because the control process exited with error code真正的信息在 journal 里# 看 docker 服务最近 50 行日志定位启动失败原因 journalctl -u docker -n 50 --no-pager-u docker限定单元-n 50只取最近 50 行--no-pager避免输出被分页卡住。常见的失败原因有三类/etc/docker/daemon.json的 JSON 语法错误少个逗号、多个逗号最常见、存储驱动不支持overlay2需要内核支持日志里会说failed to mount overlay、cgroup 挂载异常。服务起来之后docker --version只是客户端版本真正要看的是docker info# 看 Server 段是否正常重点看 Storage Driver 和 Cgroup Driver docker info 2/dev/null | grep -Ei server version|storage driver|cgroup driver输出里Server Version: 18.09.7说明 daemon 正常Storage Driver: overlay2是最理想的如果是devicemapper或者vfs说明没走对驱动性能和磁盘占用都会难看。Cgroup Driver是cgroupfs还是systemd也要留意后面如果要在这个节点上跑编排系统cgroup driver 不一致会导致节点注册失败这是个经典问题。最后拉一个镜像验证网络docker pull hello-world docker run --rm hello-world拉不动是另一个话题net/http: TLS handshake timeout或dial tcp ... i/o timeout属于镜像源和网络层的问题处理办法在下一章第五个坑里。5. 避坑六个反复翻车的点这一章把我自己踩过和帮别人排查过的六种情况写下来每条按现象、原因、解决三步走。看到对应报错直接抄解决那栏就行。5.1 repo 文件路径写成/etc/yum.repos./现象按手册原文敲vim /etc/yum.repos./kylin_aarch64.repovim 提示E212: Cant open file for writing或者更隐蔽的情况——你用的是cat 重定向文件写进了一个新建的不存在的目录如果权限允许然后yum repolist里怎么都看不到这个源。原因路径少了d/etc/yum.repos.d/才是仓库目录。手册排版时丢字符是纯粹的文档错误但新手照着敲会一头雾水。解决改成/etc/yum.repos.d/kylin_aarch64.repo。养成个习惯配完源立刻ls /etc/yum.repos.d/确认文件名再yum repolist确认仓库加载成功两步都不花时间能挡掉后面一堆“为什么源不生效”的疑问。5.2 baseurl 用了$releasever报Failed to download metadata for repo现象yum makecache或yum install时报Failed to download metadata for repo docker-ce-stable、Cannot download repomd.xml、Status code: 404有时还伴随长时间的等待。原因docker-ce 的 CentOS 仓库路径里有一段固定是centos/7而麒麟 V10 的$releasever解析成10拼出来的地址.../linux/centos/10/aarch64/stable根本不存在。另外%24basearch拼错、结尾少斜杠也会造成类似问题。解决baseurl里写死7架构段保留$basearch让它自动替换。改完yum clean all yum makecache再yum repolist看有没有报错。以后配任何第三方 el7 仓库在麒麟上都要先想一遍“这个地址里的版本段会不会被自动替换成 10”。5.3yum install docker-ce直接装nothing provides container-selinux现象Error: Problem: cannot install the best candidate for the job - nothing provides container-selinux 2:2.74 needed by docker-ce-3:20.10.17-3.el7.aarch64。原因不带版本号的yum install会挑仓库里最新的 docker-ce最新版对 container-selinux 的要求超出麒麟源能提供的范围。解决yum list docker-ce --showduplicates | sort -r看全部版本从高到低用yum install --assumeno docker-ce-版本试依赖第一个能过的就装它并且docker-ce-cli用同一版本号。不要用--skip-broken掩盖问题。5.4 安装正常但systemctl start docker失败现象Job for docker.service failed because the control process exited with error code.systemctl status docker看不出有用信息。原因大致三类。/etc/docker/daemon.json有 JSON 语法错误多一个逗号、少一个引号存储驱动不被内核支持cgroup 或 iptables 在工作环境里有冲突。解决journalctl -u docker -n 50 --no-pager看真实报错。如果是 JSON 问题用python3 -m json.tool /etc/docker/daemon.json校验一遍格式比肉眼找逗号靠谱。如果是failed to mount overlay换成storage-driver: vfs先让服务起来性能差但能跑再回头解决内核模块。改完daemon.json一律systemctl daemon-reload systemctl restart docker别只 restart。5.5 镜像拉不下来TLS handshake timeout现象docker pull hello-world卡住很久最终报net/http: TLS handshake timeout或dial tcp ...: i/o timeout。原因默认镜像仓库在公网上访问不稳定或者被限速DNS 解析慢也会加剧这个问题。装 docker 成功和拉镜像是两个独立环节前者只验证了包管理后者才验证网络。解决配镜像加速地址写进/etc/docker/daemon.json{ registry-mirrors: [https://你的加速地址], exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 } }registry-mirrors是加速地址列表按可达性排序native.cgroupdriversystemd让 cgroup 驱动和系统保持一致避免以后接入编排系统时踩坑后面两行是日志轮转不加的话/var/lib/docker/containers/*/*-json.log会把磁盘吃满这个坑通常在跑了一两个月之后才炸。改完systemctl daemon-reload systemctl restart docker用docker info看Registry Mirrors段有没有生效。5.6 装完docker: command not found或者装成了 podman 兼容包现象yum install docker执行成功docker version提示command not found或者有输出但 Server 段是 podman。原因麒麟源里docker这个名字可能指向 podman-docker 之类的兼容包它提供/usr/bin/docker的软链实际调用 podman另一种情况是只装了 docker-ce 没装 cli二进制不在 PATH 里。解决rpm -qa | grep -Ei docker|podman看清楚到底装了什么。如果发现 podman-docker先yum remove podman-docker再按版本装 docker-ce-cli 和 docker-ce。装完which docker应该指向/usr/bin/dockerdocker version的 Client 和 Server 段版本号要一致。6. 快速定位三条命令分清是源问题、依赖问题还是版本问题装不上的时候别急着换源、换版本、重装系统先花三十秒做分类。我的习惯是三步顺序固定。第一步确认仓库在不在yum repolist | grep -E docker-ce|ks10两个仓库都应该出现包数量不为 0。只有 docker-ce 没有麒麟源说明依赖解析注定失败一个都没有说明 repo 文件没生效回头查文件名和路径。第二步确认版本有哪些yum list docker-ce docker-ce-cli --showduplicates | sort -r如果只列出一两个版本说明仓库元数据没更新或者 baseurl 指错了如果列出一长串但全都装不上说明是依赖门槛问题不是版本缺失。第三步用试运行定位到底缺哪一环yum install --assumeno docker-ce-18.09.7-3.el7报错里出现nothing provides就是依赖包在源里不存在出现but X is available就是版本低了。这两句话的处置方向完全不同前者要补源或者换版本后者只能换版本。把常见报错和根因对照成一张表遇到不认识的报错先在这张表里找最像的报错片段大概率根因下一步命令Failed to download metadata for repobaseurl 路径错$releasever被替换成 10、结尾少斜杠yum repolist看完整 URLnothing provides container-selinux版本门槛超出麒麟源能提供的范围yum list --showduplicates换低版本Public key ... is not installedgpgkey 没生效或没导入重新导入 key或临时gpgcheck0No match for argument仓库里没这个版本或缓存没更新yum clean all yum makecacheJob for docker.service faileddaemon.json 语法、存储驱动、cgroupjournalctl -u docker -n 50TLS handshake timeout镜像仓库不可达配registry-mirrors后重启验证环节也有个固定的收尾动作装完必跑三条docker --version看客户端docker info看 Server 和 Storage Driverdocker run --rm hello-world看端到端通不通。三条都过才算这台机器真的能跑容器而不是“装上了”。血泪教训是我早期在这类国产化系统上装东西总想着“先把包装上再说”结果每次都在依赖上反复一周能修三四台同款机器。后来改成固定顺序先 repolist 确认仓库、再 showduplicates 确认版本、再 assumeno 确认依赖最后才动手装。从那以后我每次在新机器上装 docker不管是不是麒麟都强制把这三条命令走一遍宁可多花两分钟也不要在--skip-broken的假成功里浪费半天。这份手册的价值也在这里——它把“能装上”的那条路径固定下来了源怎么配、版本选哪个、装完怎么验照着走一遍就有结果。希望帮到你。本文还有配套的精品资源点击获取