1. 为什么要在 CentOS 7 上用 yum 装 Docker CE
先说个真实场景:我前两年接手过一批 CentOS 7.6 的存量服务器,系统是多年前就部署好的,上面跑着各种旧业务,不能轻易重装系统,也没条件上容器编排平台。当时急需在这些机器上把 Docker 跑起来,给业务做隔离和快速交付。我第一个想到的安装方式就是 yum。原因很简单:CentOS 7 的生命周期虽然已经进入维护阶段,但它依然是很多企业的生产主力系统,而 Docker 官方对 CentOS 7 的支持做得非常完整,把仓库配好之后,一条 yum 命令就能装完整个 Docker CE,包括运行时、命令行工具和配套组件。
很多人会有疑问:都什么年代了,直接下二进制包或者用脚本装不是更省事?我不否认curl -fsSL那套脚本安装确实很快,但这种方式在实际生产里不太可控。脚本会替你选择版本,也会往系统里塞一些你可能不需要的配置,出了问题你很难说清楚它到底改了哪些文件。而用 yum 安装的好处是:依赖关系由包管理器统一处理,后续升级、卸载都走标准的系统机制,安全补丁也能通过仓库及时同步。说白了,yum 装 Docker 就像你买家电走正规渠道,有包装、有保修、有说明书;脚本安装则像找人代购,东西能到,但中间过程你没法完全掌控。
这一篇我直接给你一条完整可落地的操作路径,从清理旧版本到配置仓库,再到启动验证、版本锁定和常见问题排查,全部基于我在 CentOS 7 上的实际踩坑经验。适合那些刚接触容器、准备在测试环境里体验 Docker,或者要给已有服务器批量部署 Docker 的运维和开发同学参考。
1.1 想清楚再动手:Docker CE 和 Docker 老版本的区别
Docker 早期版本在 CentOS 仓库里的叫法是docker或者docker-io,那是老一代的版本,问题不少:组件耦合在一起,升级不方便,和 systemd 的集成也一般。Docker 官方后来把产品线拆成 CE(社区版)和 EE(企业版),社区版完全免费,功能上对绝大多数团队来说完全够用。
具体到 CentOS 7,我们安装的 Docker CE 在 18.09 之后默认使用 containerd 作为容器运行时,不再直接依赖 LXC 那一套。这种架构的好处是:Docker CLI、dockerd 守护进程和 containerd 各司其职,哪怕守护进程重启,容器也不会轻易跟着挂掉。所以在排查问题的时候,你会看到docker-ce、docker-ce-cli、containerd.io三个核心包,它们缺一不可,这也是很多新手只装了 docker-ce 却启动不了服务的常见原因。
另外一个容易忽略的点:CentOS 7 的内核默认是 3.10,这个内核版本对 Docker 来说是可以用的,但如果你要用 OverlayFS 存储驱动,建议先把内核升级到 3.10.0-1160 之后的版本。我之前在一台内核停留在 3.10.0-957 的机器上跑 Docker,创建容器偶发性地出现文件系统相关报错,后来就是升级了内核小版本解决掉的。
1.2 安装前必看:系统环境与前置准备
在敲 yum 命令之前,我习惯先花一分钟确认系统现状,避免装到一半才发现问题。
首先确认系统版本,用一条命令:
cat /etc/centos-release正常会看到类似CentOS Linux release 7.9.2009 (Core)的输出。如果你的系统是 CentOS 7 的早期小版本,比如 7.2 甚至 7.0,我不建议直接装最新版 Docker CE,因为新版 containerd 对内核和 systemd 的要求更高,老系统装上去很可能遇到奇怪的问题。这时候先yum update -y把系统基础包升一遍,再继续操作。
然后要确认网络能不能正常访问外网,尤其是 Docker 的官方仓库和镜像仓库。如果你所在的网络环境有防火墙策略,至少要能访问download.docker.com和registry-1.docker.io这些地址。这里我多说一句:国内访问官方源有时候会出现超时或速度慢,我的做法是先配置阿里云或清华的镜像源,具体方法在后面第 2 步里会详细说明。
此外,还需要确认你有没有 root 权限或者 sudo 权限。整篇操作流程绝大部分都需要 root,如果你用的是普通用户,建议先sudo -i切换到 root,或者确保你的用户被授予了 NOPASSWD 的 sudo 权限,不然每一条命令都要反复输密码,效率很低。
还有一个很多人会忽略的细节:检查磁盘空间。Docker 默认会把所有镜像、容器数据都放在/var/lib/docker目录下,如果这个目录所在的分区空间不够,装上去也跑不了几个容器。我建议至少留出 10GB 以上的可用空间,生产环境根据业务需要另行评估。
2. 五步安装全流程:从配置仓库到开机自启
接下来就是重头戏。我先把五个步骤整体列出来,再逐步展开说明,每一步我都标注了为什么这么做,以及不这么做会有什么后果。整个过程我已经在多个环境里重复执行,只要系统干净、网络正常,基本都能一把过。
2.1 第 1 步:卸载可能残留的旧版本包
这一步不是必须的,但我强烈建议你执行。因为很多 CentOS 7 机器上之前可能装过老版本 Docker,或者通过其他方式装过某个不完整的包,残留的二进制文件和配置会干扰后续安装。
sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine注意,执行完这条命令之后,/var/lib/docker目录下的数据并不会被自动清理。如果你是第一次安装,这个目录本来就空着,不用管。如果你之前跑过容器,里面可能有重要的容器数据或镜像缓存,卸载之前一定要先备份或者确认不需要了。我见过有人图省事直接卸载,结果整个环境的容器数据全部丢光,那种教训十分惨痛。
另外,如果你之前用二进制方式装过 Docker,也就是手动解压过 Docker 静态二进制文件到/usr/bin下面,yum remove 是清理不干净的。手动检查一下:
ls -l /usr/bin/docker /usr/bin/dockerd /usr/bin/containerd 2>/dev/null如果这些文件还在并且不是通过 rpm 包安装的,直接删掉它们再继续。否则后面 yum 安装时可能因为文件冲突报错。
2.2 第 2 步:安装 yum-utils 并配置 Docker 官方镜像源
yum-utils 是一个工具集,里面提供了yum-config-manager命令,我们利用它来添加和管理 yum 源仓库。先执行:
sudo yum install -y yum-utils如果你的系统里已经装过了,命令会提示 nothing to do,不影响后续操作。
然后添加 Docker 官方仓库。官方文档给的是:
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo但是我实际使用中发现,国内网络直接访问download.docker.com经常很慢,甚至直接超时。这时候我会把 repo 地址换成国内镜像源。以阿里云源为例:
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo添加完之后,还需要处理一个细节:这个 repo 文件里的baseurl指向的是https://download.docker.com/linux/centos,即使你用了阿里云源,YUM 也可能因为 HTTPS 证书问题和网络原因变慢。好的做法是直接修改/etc/yum.repos.d/docker-ce.repo,把里面的download.docker.com替换成mirrors.aliyun.com:
sudo sed -i 's+download.docker.com+mirrors.aliyun.com+d' /etc/yum.repos.d/docker-ce.repo这样后续yum install时就会从国内镜像拉取 rpm 包,速度快很多。
这里必须提醒一个我踩过的坑:阿里云源是 HTTP 协议,而 Docker 官方源是 HTTPS。从安全角度讲,如果网络条件允许,优先保留官方 HTTPS 源;如果实在要用国内源,至少要确认所处的网络环境可信。另外,不要同时把官方源和多个第三方源混杂在一起,YUM 解析时如果同一个软件包在多个源里出现,容易产生版本冲突。我的习惯是在/etc/yum.repos.d/下只保留一个 docker-ce.repo,其他第三方 Docker 源全部禁用或删除。
2.3 第 3 步:安装 Docker CE 及配套组件
仓库配置好后,先更新一下 YUM 缓存,然后直接安装 Docker CE:
sudo yum makecache fast sudo yum install -y docker-ce docker-ce-cli containerd.io这里三个包要一起装。很多人只装了docker-ce,结果dockerd启动时发现找不到 containerd,或者输入 docker 命令时提示找不到 CLI 工具,其实都是因为这三个包的搭配没有装完整。
如果你需要指定版本,可以先查看仓库里有哪些可用版本:
yum list docker-ce --showduplicates | sort -r然后安装指定版本,例如:
sudo yum install -y docker-ce-3:20.10.24-3.el7 docker-ce-cli-3:20.10.24-3.el7 containerd.io-1.6.28-3.2.el7版本号前面那个3:是 epoch 号,在 CentOS 7 的 YUM 体系里必须带上,否则可能会提示找不到包。我建议不是特殊兼容性要求的话,直接装当前最新稳定版就行,后续再通过版本锁定控制升级。
安装完成后,可以用rpm -qa | grep docker验证一下安装结果。正常你会看到类似下面的输出:
docker-ce-20.10.24-3.el7.x86_64 docker-ce-cli-20.10.24-3.el7.x86_64 containerd.io-1.6.28-3.2.el7.x86_64到这里,软件包层面的安装就算完成了,但服务还没有启动。
2.4 第 4 步:启动服务并验证运行状态
安装完包之后,Docker 守护进程并不会自动启动,至少在我用过的所有 CentOS 7 版本里都这样。所以需要手动设置开机自启并立即启动:
sudo systemctl start docker sudo systemctl enable docker第一条命令启动服务,第二条命令注册开机自启。很多老手会倒过来先 enable 再 start,也没问题,但我觉得先 start 再 enable 更符合直觉:先确认服务能拉起来,再设置长期生效。
启动之后,我先看服务状态:
sudo systemctl status docker如果看到active (running),说明服务正常。这里有个细节值得注意:CentOS 7 的 systemd 会把服务日志写到 journal 里,如果启动失败,可以用sudo journalctl -u docker.service -n 50查看最近的日志,这个排查动作我在后面第 4 章还要细说。
为了进一步确认 Docker 能用,跑一下官方提供的测试镜像:
sudo docker run hello-world这个命令会先从 Docker Hub 拉取一个名为hello-world的测试镜像,然后创建容器运行它。如果能看到Hello from Docker!的输出,说明整套链路已经走通。首次运行需要拉取镜像,所以会花一点时间,如果你的网络访问 Docker Hub 很慢,可以先参考第 3.2 节的内容配置镜像加速器,然后再执行这条命令。
2.5 第 5 步:将普通用户加入 docker 组(可选但强烈建议)
Docker 默认只允许 root 用户或 docker 组里的用户访问/var/run/docker.sock这个 socket 文件。也就是说,你用普通用户执行 docker 命令,大概率会收到这样的提示:
permission denied while trying to connect to the Docker daemon socket解决办法很简单,把当前用户加入 docker 组:
sudo usermod -aG docker $USER这里注意两点:第一,执行完这条命令后,当前用户必须退出重新登录,或者执行:
newgrp docker让新的组成员关系立即生效。第二,把用户加入 docker 组等同于赋予该用户 root 级别的系统权限,因为 docker 命令本身可以挂载宿主机目录、操作宿主机的进程和网络。如果你管理的是生产服务器,不建议随便把普通用户加进来,宁可让开发者通过 sudo 来执行 docker 命令,安全边界会更清晰。
五步到这里就全部结束了。如果你只是想在个人开发机或者测试环境里把 Docker 跑起来,那么到这一步已经可以开始拉镜像、跑容器了。但我在实际生产环境里不会就此收手,接下来要做的几件事,能帮你避免很多后续运维上的麻烦。
3. 装完别急着跑:版本锁定、加速器配置和数据目录迁移
每次有同事装完 Docker 就急着往上丢业务,我都会劝他先花十分钟把下面的配置搞定。这些都是我从多次故障里总结出来的,提前做好,后面能省非常多的心力。
3.1 为什么我总是强调版本锁定
Docker 的新版本发布节奏非常快,尤其是一些大版本更新,往往伴随着架构调整和配置项变更。比如 Docker 20.10 迁移到 21.11 后,部分启动参数有了调整;再比如 containerd 版本升级后,如果你还在用旧的存储驱动配置,可能会直接无法启动。一旦在生产环境里执行yum update而忘了排除 Docker 相关包,系统很可能会把 Docker 升级到新版本,然后你的容器服务就静悄悄地挂了。
所以我的做法是,安装完成后立刻给 Docker 相关包加上版本锁定,通过 yum 插件实现:
sudo yum install -y yum-plugin-versionlock sudo yum versionlock add docker-ce docker-ce-cli containerd.io查看哪些包被锁定了:
sudo yum versionlock list如果后续确实需要升级,先解除锁定再升级:
sudo yum versionlock delete docker-ce docker-ce-cli containerd.io升级完成后再重新加上锁定。这是一个很不起眼但价值极高的习惯,尤其是当你管理多台服务器时,能有效避免因为版本不一致导致的环境差异。
3.2 镜像加速器的配置与坑
在国内网络环境下,拉取 Docker Hub 上的镜像经常慢得让人怀疑人生。解决办法是配置镜像加速器。Docker 的镜像加速器配置在/etc/docker/daemon.json文件里,如果这个文件不存在,直接创建即可。
一个常见的配置示例:
{ "registry-mirrors": ["https://your-mirror.example.com"] }最多可以配置多个加速器地址,Docker 会依次尝试。配置完成后重启 Docker 服务:
sudo systemctl daemon-reload sudo systemctl restart docker我在这里遇到过几个坑。第一个是 daemon.json 的 JSON 格式问题,稍微多一个逗号或者少一个引号,Docker 服务就会起不来,而且报错信息很隐晦,只告诉你 failed to start daemon。解决方法是用python -m json.tool /etc/docker/daemon.json或者jq .先校验一下再重启。
第二个是加速器有时只对部分路径生效。例如你配置了公共加速器,但某些镜像仓库有自己的域名,这时候加速器并不会生效,因为你请求的是那个仓库自己的地址,而不是 Docker Hub。理解这一点后,遇到拉取慢的问题就不会再盲目怀疑加速器配置有问题了。
第三个是公共加速器的可用性会变化。我最早用的加速器地址后来慢慢失效,镜像拉不下来,害我排查了很久。所以我会在自己维护的机器上定期测试加速器效果,发现不稳定就及时换掉。
3.3 数据目录迁移:/var/lib/docker 挪个家
Docker 所有数据,包括镜像、容器层、卷,都默认存在/var/lib/docker。如果你的系统盘很小,或者/var分区空间紧张,那么这个目录迟早会撑爆磁盘。我在生产机上通常会把数据目录迁移到大容量数据盘。
迁移步骤不算复杂,但一定要按顺序来:
sudo systemctl stop docker sudo mkdir -p /data/docker sudo rsync -aS --progress /var/lib/docker/ /data/docker/数据同步完成后,编辑/etc/docker/daemon.json,加上:
{ "data-root": "/data/docker" }然后启动 Docker:
sudo systemctl start docker启动后先验证原有镜像和容器是否还在:
sudo docker images sudo docker ps -a确认无误后,再删掉旧目录:
sudo rm -rf /var/lib/docker这里有两个容易踩的坑。第一,千万不要在没有停止 Docker 服务的情况下直接同步数据,否则容器还在写入数据,同步结果不一致。第二,不要直接动/var/lib/docker里的文件来“迁移”,正确的做法是通过>sudo semanage fcontext -a -e /var/lib/docker /data/docker sudo restorecon -Rv /data/docker
如果系统里没有 semanage 命令,先安装policycoreutils-python。但说实话,如果你对 SELinux 不熟,我更推荐直接检查getenforce的结果,如果状态是 Enforcing,可以考虑临时用setenforce 0验证是否是 SELinux 导致的问题,确认后再决定是调整策略还是临时关闭。
4. 常见问题与排查实录
这一部分是靠真实故障堆出来的经验。我把我在 CentOS 7 上安装和使用 Docker CE 过程中遇到的典型问题整理成速查表,每个问题都给出了定位思路和解决办法。你可以直接对着排查。
4.1 安装时提示 package docker-ce 未找到?
这个提示几乎都是在仓库配置错误或者缓存未刷新时出现的。第一步先检查仓库文件是否存在:
ls -l /etc/yum.repos.d/docker-ce.repo如果文件不存在,说明第 2.2 步没执行成功,重新执行yum-config-manager --add-repo。
如果文件存在,再检查仓库里的包列表:
yum list docker-ce --showduplicates如果列表为空,很可能是你下载的 repo 文件里baseurl指向了不正确的地址,或者系统架构不是 x86_64。CentOS 7 上 Docker 官方只提供 x86_64 和少量其他架构的包,如果你用的是 ARM 版本或某些国产 CPU 环境,就需要去找对应的容器镜像源。
还有一种常见情况:你添加了 repo,但没有执行yum makecache fast。YUM 的缓存可能还是旧的,导致找不到新加入的软件包。刷新缓存后再次安装,基本都能解决。
4.2 启动失败:Job for docker.service failed
这条报错背后往往藏着多种原因。我先讲最常见的几种。
第一种是 daemon.json 配置错误。检查方式我前面提过,用python -m json.tool校验 JSON。再直接看守护进程日志:
sudo journalctl -u docker.service -n 50日志里如果出现类似unable to configure the Docker daemon with file /etc/docker/daemon.json的提示,基本就是 JSON 格式问题。
第二种是内核模块或者 iptables 相关的问题。Docker 使用 iptables 来做网络隔离和端口映射,如果服务器的 iptables 规则被改乱过,或者内核缺少相关模块,会导致启动失败。可以先尝试:
sudo systemctl restart iptables sudo systemctl restart docker如果还不行,检查内核模块:
lsmod | grep br_netfilter如果没有输出,手动加载:
sudo modprobe br_netfilter并把它写入/etc/modules-load.d/br_netfilter.conf,保证重启后自动加载。
第三种是系统磁盘空间不足或者 inode 耗尽。用df -h和df -i看一下,如果某个分区满了,Docker 在初始化时会报错。尤其是/run目录,Docker 会往里面放一些运行时文件,如果cat /sys/fs/cgroup挂载异常,也会导致 cgroup 相关报错。
4.3 运行 hello-world 报权限错误或 cgroup 问题
假如你已经启动了 Docker 服务,但运行容器时报权限错误,先确认当前用户是否在 docker 组里,或者是否用了 sudo。如果服务是 root 启动的,普通用户访问 socket 就会权限不足。
另外,CentOS 7 的 cgroup 驱动在 Docker 和 systemd 之间存在一个经典问题:如果 Docker 守护进程使用的是cgroupfs驱动,而系统初始化使用systemd作为 cgroup 驱动,在容器里可能会产生资源统计不准确甚至操作被拒绝的问题。解决方法是在/etc/docker/daemon.json中显式设置:
{ "exec-opts": ["native.cgroupdriver=systemd"] }修改后重启 Docker。这个配置在 Docker 后四版本里尤其重要,尤其是在你后面要用到 Kubernetes 或者容器编排平台时,如果 cgroup 驱动不统一,节点状态会一直处于 NotReady。
还有一种报错是关于cgroup: cannot found或者failed to create cgroup,这大多是因为系统内核里 cgroup 相关配置被关闭。由于 CentOS 7 默认是开启的,出现这种问题往往是你之前优化过内核参数,把某些 group 类型关掉了。恢复一下/boot下内核参数文件里与 cgroup 相关的配置,再重启系统即可。
4.4 卸载重装时要打扫干净的残留文件
不要轻易卸载 Docker,但如果确实要清掉重来,绝不能只执行一个yum remove就完事。我之前在测试环境里想彻底重置 Docker,结果残留的配置文件和网络规则导致第二次安装后服务仍然异常。正确的清理步骤如下:
停止服务并移除软件包:
sudo systemctl stop docker sudo yum remove -y docker-ce docker-ce-cli containerd.io删除配置和运行目录:
sudo rm -rf /var/lib/docker sudo rm -rf /etc/docker清理 iptables 里 Docker 产生的链:
sudo iptables -F FORWARD到这里,系统里 Docker 的痕迹基本就清完了。如果你还需要把镜像和容器数据也彻底抹掉,再把/var/lib/containerd等 containerd 相关目录一并删除。这一步请务必备份重要数据再做,我有一次误操作删了某个环境的数据卷,损失不小,后来凡是跟删数据相关的操作,我都会先在执行前跑一遍ls确认路径。
5. 最后再聊点使用感受
这套五步安装法我在不同版本的 CentOS 7 上验证了很多次,包括虚拟机、物理机、云服务器,稳定性都还不错。最核心的体验是:只要仓库配置正确、依赖包完整,yum 安装几乎不会出什么岔子。相比之下,脚本安装虽然快,但在内网离线环境里反而不如这种先下载好 rpm 包再离线安装的方式可控制。我个人习惯是先在一台机器上配置好一切,然后通过 yum 的缓存把安装包留存下来,这样后续新机器即使外网受限,也能很快复现同样的环境。
另外,安装完成并不是终点。真正有价值的不是 Docker 本身,而是你用它跑起的业务、建立的镜像构建流程、以及容器化之后带来的交付效率提升。CentOS 7 本身已经处于维护期,如果你有长期规划,我建议逐步考虑迁移到更新的操作系统,但在此之前,用好 yum 这个最基础、最可靠的安装路径,完全可以把 Docker 的服务稳定跑起来。最后再分享一个小技巧:安装完成后,把/etc/yum.repos.d/docker-ce.repo备份到单独的目录或者记录到文档里,以后新机器部署的时候直接复制过去就行,省得每次都要重新处理替换地址这一堆事。