银河麒麟aarch64安装Docker:源配置、版本锁定与依赖排错
简介:面向在银河麒麟 V10 SP1 Server 上部署容器环境的运维人员与开发者的实操手册,聚焦官方源缺少 Docker 软件包、依赖组件难以更新等典型问题,给出可落地的安装路径与注意事项。压缩包仅含 1 个 docx 文档,体积约 17KB,篇幅精简但结构完整,依次覆盖配置阿里 Docker CE 源与麒麟官方依赖源、安装指定版本 docker-ce-cli 与 docker-ce、启动服务及版本核验等环节,并对 arm64 源地址、gpgcheck 设置等细节给出示例。文档还专门记录了无法通过 yum 安装最新版 Docker 的报错现象与原因分析,并注明可用版本为 18.09.7,便于读者对照排查依赖冲突、少走弯路。目前已有 7220 人学习下载,适合需要快速完成内网或信创环境容器化改造的初中级用户参考,也适合在离线或受限网络环境中按文档逐步操作、快速验证部署结果。
1. aarch64 上的 docker,难在版本不在命令
在银河麒麟 v10 sp1 server 上做 docker 安装,翻车的点几乎从来不是yum install这一行命令本身,而是它前面那两步:源配没配对、架构认没认清。这台机器大概率是 aarch64,而网上绝大多数 docker 安装教程是照着 x86_64 写的,你照着抄,yum会给你一句nothing provides,让你以为是网络问题,反复yum clean all折腾半小时。更麻烦的是官方源里根本没有 docker server 的包,只能挂第三方源,再补一个麒麟官方源兜依赖,两个源缺一个都装不完。这篇记录的就是 docker 银河麒麟这套组合的完整落地过程:从架构确认、源文件怎么写、版本为什么必须锁在 18.09.7-3.el7,到装崩了怎么从日志里把原因挖出来。适合手上正卡在依赖报错上的运维和刚接手麒麟服务器的开发。
2. 装前摸底:三条命令确认架构与源状态
动手改配置之前,先花两分钟把机器的底细摸清楚。这一步省下来的时间,后面会以小时为单位还给你。麒麟 v10 sp1 server 同时存在 x86_64 和 aarch64 两个发行版本,而跑在飞腾、鲲鹏机器上的基本都是 aarch64。docker 官方的 rpm 包是按架构分开编的,架构对不上,包名再正确也装不上,报错信息还偏偏不直说架构问题,只告诉你某个依赖没有提供方。
2.1 确认 CPU 架构与系统版本
先跑三行,把机器身份确认下来:
uname -m # 关键:输出 aarch64 还是 x86_64,决定后面所有包的选择 cat /etc/os-release # 看 VERSION 与 ID,确认是 v10 sp1 而不是 v10 sp2/sp3 getconf LONG_BIT # 输出 64,确认是 64 位用户态uname -m是最不能被跳过的一条。我见过有人在 aarch64 机器上按 x86_64 教程装,yum报no package docker-ce available,然后一路怀疑源地址写错、DNS 不通、防火墙拦截,其实只是仓库路径里的$basearch展开了aarch64,而那份教程让人把 baseurl 写死成了x86_64。/etc/os-release里的 VERSION 字段同样要看,sp1 和后续小版本的官方源路径不一样,照抄别人的sp1-openstack-q路径到 sp2 上,yum makecache会直接 404。
顺带把磁盘也看一眼,df -h /var建议留 20G 以上。docker 的镜像层、容器日志全压在/var/lib/docker下,空间不够时 docker 起得来,但跑两个镜像就no space left on device,而报错发生在业务侧,排查方向容易跑偏。
2.2 看清当前 yum 源的真实状态
摸底第二步是看源,不是看有没有文件,而是看哪些源真的enabled=1:
ls -l /etc/yum.repos.d/ # 列出所有 repo 文件,注意有没有 .repo.bak 之类的残留 yum repolist # 只显示启用的源及包数量 yum repolist all | grep -iE 'docker|kylin' # 单独确认 docker 源和麒麟源的状态yum repolist输出里每个源后面的包数量是判断源是否健康的直接依据。如果某个源的包数量显示为 0,或者压根没出现在列表里,说明它的enabled是 0 或者 baseurl 不可达,后面装 docker 时依赖就会缺。很多"装不上"的现场,其实是上一次装失败留下的半成品 repo 文件还在目录里,和新写的源互相打架,yum合并元数据时挑了一个更老的版本。
我一般会在改配置前先备份一次:mkdir -p /root/repo-bak && cp /etc/yum.repos.d/*.repo /root/repo-bak/。这不是仪式感,是后悔药。改坏了直接cp回来,比一条条回忆自己删了什么快得多。
2.3 版本选择:为什么是 18.09.7-3.el7
版本这一节是整篇文章的分水岭。docker 官方在 CentOS 7 仓库里同时提供 18.09、19.03、20.10 等多个大版本,yum install docker-ce不带版本号时,fresh 的服务器会去挑那个"最新可用"的,而最新版的依赖链在麒麟上恰恰断掉。原文给出的报错就是典型:
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.aarch6420.10 系列要求container-selinux至少到2:2.74,而麒麟 v10 sp1 官方源里能提供的版本低于这个门槛。这不是源写错了,是这套系统的软件基线还没跟上 docker 新版的要求。18.09.7 对container-selinux的版本要求宽松得多,能落在麒麟现有依赖范围内。
| 对比项 | docker-ce 18.09.7-3.el7 | docker-ce 20.10.x |
|---|---|---|
| container-selinux 要求 | 较低,麒麟源可满足 | >= 2:2.74,麒麟源不满足 |
| 依赖链长度 | 短,cli 与 engine 版本对应简单 | 长,牵连 containerd.io 与 selinux 策略 |
| 在麒麟 v10 sp1 上的结果 | 可直接安装跑通 | 需自行编译或强升依赖,风险高 |
| 适用场景 | 生产部署、内网离线环境 | 新特性验证 |
包名里的el7不是"给麒麟 7 用的",它是 docker 官方为 CentOS 7 及其兼容发行版编译的包标签。麒麟 v10 的 glibc 与 ABI 兼容这一档,所以能装。3.el7中的3是打包修订号,不是版本号的一部分,写yum install docker-ce-18.09.7时不带-3.el7,yum 会帮你挑仓库里该版本的最新修订,通常也是这个,但明确写全更稳妥。
3. 配置 yum 源:两个 repo 文件各管一段
银河麒麟的官方源里查不到 docker server 的软件包,这一点在动手前就得接受,不要再去官方源里翻。可行的路径是挂第三方 docker-ce 镜像源拿 docker 包,同时保留麒麟官方源用来兜底依赖包。两个源各管一段,分工明确,缺一段就装不完整。
3.1 写 docker-ce.repo,把 $basearch 留给系统
第一个文件是 docker 包来源,直接写在/etc/yum.repos.d/docker-ce.repo:
cat > /etc/yum.repos.d/docker-ce.repo <<'EOF' [docker-ce-stable] name=Docker CE Stable - 7 baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/$basearch/stable enabled=1 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg EOF逐项说明这几个参数,因为改动它们最容易出事:
baseurl里的$basearch是 yum 的变量,运行时自动展开成aarch64或x86_64。不要手写成具体架构,写成具体值以后,这份配置搬到另一台机器上就废了,而这类错误往往在几个月后才暴露。- 路径里的
centos/7是镜像站的目录约定,和本机系统版本无关。麒麟 v10 对应的是centos/7这一档,不要因为系统叫 v10 就把路径改成centos/10,那个目录不存在。 gpgcheck=1表示校验包签名。第一次安装时会去gpgkey拉公钥,如果这台机器不能出网,校验会卡住。内网离线环境可以把gpgcheck临时置 0,但装完后建议补回并手动rpm --import公钥,否则你等于放弃了"包有没有被篡改"这一层保护。enabled=1让这个源默认参与解析。文件里只保留[docker-ce-stable]一个段,是为了避免stable、test、nightly多个段同时启用后,yum在解析时挑到 test 里的预发布版本。
3.2 补麒麟官方源,专门用来装依赖
第二个文件负责依赖,写在/etc/yum.repos.d/kylin_aarch64.repo:
cat > /etc/yum.repos.d/kylin_aarch64.repo <<'EOF' [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 EOF这个源里最关键的是baseurl最后那段v10/sp1-openstack-q/aarch64/os。sp1要和你机器上/etc/os-release的版本对得上,aarch64要和uname -m对得上,openstack-q是麒麟为这套系统提供的软件集合目录名。三个片段任何一个不对,yum makecache就会返回 404,而 404 的表现是"源里啥都没有",不是明确的路径报错,很容易误判。
gpgcheck = 0在这里是一个权衡。麒麟官方源的签名配置在不同小版本上不完全一致,开了校验反而可能因为缺公钥导致整源不可用。我的做法是:内网、可信网络环境下保持 0 先把包装上,装完之后如果要做安全加固,再单独去补公钥并改回 1,而不是指望这次安装顺手把校验也做对。注意gpgcheck等号两侧可以有空格,但段名[ks10-os-media]必须独占一行,顶格写,前面不能有空格。
3.3 刷新缓存并验证源是否真的可用
两个文件写完,不要急着 install,先把缓存刷干净再验证:
yum clean all # 清掉旧元数据,避免新旧源混用导致解析到不存在的版本 yum makecache # 重新拉取所有启用源的 repomd.xml 与包列表 yum repolist # 确认 docker-ce-stable 与 ks10-os-media 都在,且包数不为 0接着单独验证 docker 源里到底有没有你要的那个版本,这一步能把"版本不存在"和"依赖缺失"两种失败提前区分开:
yum list available 'docker-ce*' --showduplicates | sort -r | head -20 yum list available container-selinux --showduplicates第一条命令列出 docker 源里所有可用的 docker-ce、docker-ce-cli 版本,--showduplicates不加的话 yum 只显示每个包的最新一个,你就看不到 18.09.7 还在不在仓库里。第二条用来确认麒麟源里container-selinux的实际版本,如果它的版本低于你要装的 docker 所要求的门槛,那这条路走不通,得换版本而不是换源。常见做法是先把这两条的输出记下来,后面报错时对照,能省掉一轮猜测。
4. 锁定版本安装:先 cli 后 server,顺序反了就报依赖
到这一步,源是通的,版本也确认存在,真正开始装。这里有个反直觉的地方:docker 的两个主包必须先装 cli,再装 engine,顺序反了,yum 会在解析 engine 依赖时去仓库里挑最新的 cli,然后被最新 cli 的依赖链拖进坑里。这不是洁癖,是这套环境里最值钱的一条经验。
4.1 先装 docker-ce-cli-18.09.7-3.el7
yum install -y docker-ce-cli-18.09.7-3.el7包名拆开看:docker-ce-cli是包名,18.09.7是版本,3.el7是发布修订。省略架构后缀是故意的,让 yum 按本机$basearch去匹配,麒麟源里只有 aarch64 的包,不会歧义。执行完用rpm -q docker-ce-cli确认落地的完整包名是docker-ce-cli-18.09.7-3.el7.aarch64,如果显示的是 20.10 之类,说明 yum 没找到指定版本、退而装了可用的最新版,这时候不要继续往下走,回到 3.3 检查源。
为什么先装 cli:engine 包在元数据里对 cli 有精确到小版本的依赖。直接yum install docker-ce-18.09.7-3.el7时,yum 的依赖解析器会先看本地已装的 cli,没有的话就去仓库找,而它倾向于挑最新的那个满足者,也就是 20.10 的 cli,再往后就撞上container-selinux >= 2:2.74这堵墙。先把 cli 钉死在 18.09.7,等于给后面的解析器加了一条硬约束,它只能在这个版本上找解。
4.2 再装 docker-ce-18.09.7-3.el7
yum install -y docker-ce-18.09.7-3.el7这一步会连带装containerd.io等运行时依赖。如果这时候仍然报nothing provides container-selinux,先别急着加--skip-broken,那个参数的含义是"跳过装不上的包继续装",结果往往是 docker-ce 装了一半、依赖缺一块,系统停在一个既不能跑也卸不干净的中间态。正确的处理顺序是:
yum install -y container-selinux # 先从麒麟源把依赖补上 yum install -y docker-ce-18.09.7-3.el7 # 再回头装 engine如果container-selinux在麒麟源里也找不到,说明ks10-os-media这个源的路径写错了或者缓存没刷,回 3.3 重新验证,而不是去找别的野源。原文里提到的--nobest是另一回事,它让 yum 在找不到最优解时接受次优解,只在你确认版本兼容的前提下作为临时手段,装完必须核对rpm -qa | grep docker的实际版本,别默认它装对了。
4.3 启动服务并设为开机自启
systemctl start docker # 立即启动,失败会直接返回 Job for docker.service failed systemctl enable docker # 设为开机自启,麒麟服务器重启后 docker 不会自己回来 systemctl status docker --no-pager # 看 Active 是否为 active (running)systemctl start成功不代表下次重启还能起来,enable这一步经常被漏掉。表现是当天一切正常,过几天机房断电恢复,业务容器全没了,人还以为 docker 挂了。status那一行的输出里除了active (running),还要看下面有没有Warning,daemon 启动时的一些兼容性告警只在这里出现一次,不主动看就永远看不到。
启动失败的现场排查顺序固定为:systemctl status docker --no-pager看退出码,journalctl -u docker -n 100 --no-pager看完整日志。日志里的第一行错误才是根因,后面几行往往是它引发的连锁反应。常见的是daemon.json语法错、cgroup driver 冲突、/var/lib/docker权限被改过。
4.4 写一份 daemon.json,把日志和 cgroup 定下来
docker 起来之后,建议立刻补一份 daemon 配置,而不是等磁盘被日志撑爆再回头改:
mkdir -p /etc/docker cat > /etc/docker/daemon.json <<'EOF' { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" } } EOF systemctl daemon-reload systemctl restart dockernative.cgroupdriver=systemd让 docker 与 systemd 用同一套 cgroup 管理,麒麟 v10 默认走 systemd,不加这一项,后续接 kubelet 之类的组件时会因为 driver 不一致直接拒绝启动,而那个报错往往出现在几天后的另一个场景里,很难联想到是 docker 这边的配置。log-opts里的max-size和max-file是硬上限,单文件 100M、最多保留 3 个,单个容器日志封顶 300M。不加这两项,一个死循环打日志的容器几小时就能把/var写满。
如果现场有内网镜像仓库,顺手在同一个 json 里加"registry-mirrors": ["https://<你的镜像加速地址>"],注意 json 不能写注释,加字段时把逗号位置检查一遍,少一个逗号 docker 就起不来,报错还只说unable to configure the Docker daemon。改完必须daemon-reload再restart,只 restart 不 reload 在某些 systemd 版本上不会重新读取 unit 变更。
5. 避坑与排查:五条装坏了的现场记录
下面这五条都是我在麒麟上真实遇到过的,按"现象 → 原因 → 解决"记,症状描述尽量保留原始报错,方便你直接搜关键字对上号。
第一条:装最新版时nothing provides container-selinux >= 2:2.74
现象是yum install docker-ce直接失败,报错里点名docker-ce-3:20.10.17-3.el7.aarch64。原因是 yum 挑中了仓库里最新的 20.10,而它的依赖门槛超过了麒麟官方源能提供的container-selinux版本。解决不是强装,而是回到 2.3 选定的 18.09.7,并按 4.1、4.2 的顺序装。硬要上 20.10 的话,得自己解决 selinux 策略包,那是另一个工作量级的事,不建议在生产机上试。
第二条:装完docker --version提示 command not found
现象是 yum 显示安装成功,敲docker却说找不到命令。原因通常有三个:一是只装了 engine 没装 cli(某些手动 rpm 安装的场景),二是机器上装过podman-docker之类的替代包,/usr/bin/docker被它占了或者被卸掉了,三是 shell 的命令哈希缓存还指向旧路径。排查用:
rpm -qa | grep -i docker # 确认 docker-ce 与 docker-ce-cli 都在 which -a docker # 看实际解析到哪个路径 hash -r # 清掉 shell 的命令缓存后重试 rpm -ql docker-ce-cli | grep bin # 确认 cli 到底把二进制装哪了rpm -ql那条最直接,如果输出里根本没有/usr/bin/docker,那就是包没装对,回 4.1 重来,不要在 PATH 上折腾。
第三条:systemctl start docker失败,状态显示 failed
现象是启动命令返回Job for docker.service failed because the control process exited with error code。原因是 daemon 配置有语法错、cgroup driver 与系统不一致、/var/lib/docker磁盘满或者权限被改。解决靠日志:journalctl -u docker -n 100 --no-pager,从第一条 ERROR 读起。如果日志里出现failed to start daemon: error initializing graphdriver,基本是存储目录损坏,常见做法是停服务、把/var/lib/docker改名备份、重启让 docker 重建目录,再从镜像仓库重新拉镜像,而不是直接删目录,删之前你永远不知道里面有没有没推送过的镜像。
第四条:yum makecache报 404 或 GPG 校验失败
现象是刷新缓存时某个源返回repomd.xml: [Errno 14] HTTP Error 404,或者提示Public key for xxx.rpm is not installed。前者是 baseurl 路径错,最常见的是sp1写成别的版本号、或者aarch64和x86_64写反,用curl -I <baseurl>/repodata/repomd.xml单独测一次就能定位。后者是 GPG 公钥没导入,内网环境可以先在该源里把gpgcheck置 0 完成安装,事后用rpm --import补上公钥再改回 1,但要知道这中间存在一个不校验的窗口期。
第五条:重装或降级后版本没变化
现象是明明指定了 18.09.7,装完docker --version还是旧的新版本,或者yum downgrade被拒绝。原因是 yum 缓存里还留着旧元数据、系统里存在更高版本的已安装包导致降级需要显式允许、或者仓库里那个精确版本已经被镜像站清理。解决是yum clean all && yum makecache后重试,仍不行就rpm -qa | grep -i docker把现有包列全,逐个yum remove干净再装。装完核对版本这一步不能省,rpm -q docker-ce docker-ce-cli同时看两个包,只看docker --version会漏掉 cli 版本不一致的情况。
6. 装完怎么验证:从 --version 到一次真实容器跑通
docker --version打出Docker version 18.09.7, build 2d0083d只说明二进制在,不说明服务能用。我习惯按下面这张表逐项过一遍,全绿才算这套环境真的装完了:
| 验证项 | 命令 | 期望结果 |
|---|---|---|
| 客户端与服务端版本 | docker version | Client 与 Server 两段都输出,Server 段不为空 |
| 守护进程信息 | docker info | 能输出 Architecture、Cgroup Driver、Storage Driver |
| 服务运行状态 | systemctl is-active docker | 输出active |
| 开机自启 | systemctl is-enabled docker | 输出enabled |
| 拉取与运行 | docker run --rm hello-world | 打印 Hello from Docker 后正常退出 |
docker version和docker --version的区别要分清:前者会向 daemon 发起一次请求,如果服务端没起来,输出里 Server 段会显示Cannot connect to the Docker daemon,而--version只读本地二进制,服务挂了它照样打印版本号。这就是为什么很多人以为装好了,实际 daemon 根本没跑。docker info里的Cgroup Driver要确认是systemd,和 4.4 里配的一致;Storage Driver在麒麟上常见是overlay2,如果是vfs,说明底层文件系统不支持 overlay,容器性能会差一个量级,得考虑换数据盘。
内网离线环境跑不了hello-world的在线拉取,改成导入本地镜像再跑:
docker load -i /root/hello-world.tar # 导入事先准备好的镜像归档 docker images | grep hello-world # 确认镜像已在本地 docker run --rm hello-world # 用本地镜像起一次,验证运行时链路docker load从 tar 归档恢复镜像,--rm让容器退出后自动清理,避免留下一堆 Exited 状态的残留。这一步能跑通,说明镜像层、存储驱动、cgroup、网络命名空间这几条链路都是通的,比任何版本号输出都有说服力。
最后再补一个重启验证,这是最容易漏也最容易出事的:先systemctl restart docker,再docker ps看容器有没有按预期回来。如果业务容器没有配--restart策略,重启后不会自动拉起,这属于容器本身的配置问题,不是 docker 装坏了,但现场经常混在一起报。我一般会在交付前把这条单独走一遍,确认docker ps -a里的容器状态和重启前一致。
从那以后我每次在麒麟上装 docker,都会强制走一遍这套顺序:先uname -m确认架构,再yum repolist确认两个源都活着,版本号写全18.09.7-3.el7而不是简写,装完必跑docker version看 Server 段。这套动作多花五分钟,能挡掉后面绝大多数"为什么装上了却用不了"的追问。希望帮到你。
本文还有配套的精品资源,点击获取