前阵子有个老同事联系我,说手上还有好几台 CentOS 7 的服务器在跑业务,最近要在这批机器上部署 Docker 环境,结果照着网上乱七八糟的教程试了好几遍,不是 yum 源报错就是 Docker 启动失败。他问我:CentOS 7 不是已经停止维护了吗?为什么还有这么多人用?到底怎么装 Docker 才不踩坑?
这问题我太有感触了。我自己的生产环境里,CentOS 7 的存量机器占了相当比例,原因其实很简单:业务跑得好好的,没必要为了追新系统去动底层;再加上不少老项目的部署文档、脚本都是基于 CentOS 7 写的,迁移成本不小。所以“CentOS 7 安装 Docker”这个需求,短期内不会消失,而且会一直有人问。
这篇博文,我就把自己在 CentOS 7 上装 Docker 的完整过程、选型思路、遇到的坑和解决方案一次性讲清楚,保证你照着做就能把环境跑起来。
1. 为什么还在给 CentOS 7 装 Docker:先看清环境再动手
1.1 CentOS 7 的现状与 Docker 兼容性判断
很多人上来就问“CentOS 7 能不能装 Docker”,其实这个问题应该拆成两层看:第一层是 Docker 官方还支不支持 CentOS 7,第二层是你那台机器的实际状态能不能跑起来。
从官方支持角度说,Docker Engine 在 CentOS 7 上是长期支持的安装目标,官方仓库里依然保留着 docker-ce 的 RPM 包,安装源、依赖关系都维护得好好的。虽然 CentOS 7 本身进入了维护尾声,但 Docker 官方并没有把 CentOS 7 从支持列表里踢出去,至少在主流版本上仍然可用。
从实际运行角度说,Docker 依赖 Linux 内核特性,比如 cgroups、namespaces、网络桥接等。CentOS 7 默认内核是 3.10 系列,这个内核版本跑 Docker 是没问题的,关键是别乱升级内核、别乱改内核参数。我见过有人为了“性能更好”跑去编译新版内核,结果 Docker 存储驱动和网络模块反而不兼容了,折腾半天又退回原版内核。
1.2 安装前必须确认的三件事
在按任何教程操作之前,我建议你先花三分钟把这些检查做完,可以帮你后面少踩很多坑。
检查系统版本,确认你真的在 CentOS 7 上,而不是 CentOS 8 或者 Stream,因为不同大版本的 yum 源和包管理逻辑不一样:
bash复制cat /etc/redhat-release
检查内核版本,确保满足 Docker 的最低要求。CentOS 7 默认的 3.10 内核可以跑,但如果你用的是老得离谱的 2.6 内核,那还是先升级系统吧:
bash复制uname -r
检查网络连通性,这一步最容易被忽略。Docker 安装过程中需要从 yum 源拉取软件包,如果服务器在内网、没有外网权限,或者 yum 源没有事先配好,安装过程会卡在依赖解析那一步,报一堆 Cannot retrieve metalink for repository 之类的错误:
bash复制yum makecache fast
这一步的意义不仅仅是检查网络,还会把 yum 缓存刷新一遍,避免安装时因为缓存过期导致找不到软件包。如果你是在内网环境,需要提前把 docker-ce 的 RPM 包下载好,做成离线源或者直接用 rpm -ivh 安装,这块内容比较多,后面专门说。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 安装方案选型:最容易翻车的两个岔路口
2.1 官方 yum 源 vs 国内镜像源
CentOS 7 安装 Docker 的第一步是配置 yum 源,这一步看着简单,却是翻车重灾区。你可能会想,直接用 Docker 官方源不就行了?理论上没问题,实际操作中你会发现服务器拉取速度极其感人,尤其在网络环境不理想的情况下,一个 docker-ce 的 metadata 就要下载半天,更别说后面还要拉 containerd、docker-ce-cli 这些依赖包。
我个人的建议是,直接使用国内镜像源。以阿里云镜像站为例,配置方式如下:
bash复制yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
这里要说明两点。第一,yum-utils 提供 yum-config-manager 命令,是用来把 repo 文件写到 /etc/yum.repos.d/ 目录下的工具;device-mapper-persistent-data 和 lvm2 是 Docker 存储驱动 devicemapper 可能用到的依赖,虽然现在新版 Docker 默认用 overlay2,但装上它们可以避免一些老版本插件报错。
第二,如果你拿到的是官方源配置文件,记得检查一下里面的 baseurl 是否被正确替换成镜像地址。阿里云镜像站添加 repo 后,配置文件里的地址已经自动指向阿里云,不需要手动改。
2.2 Docker CE 版本选择:不是越新越好
同样是 CentOS 7,装哪个版本的 Docker,也是有讲究的。我见过不少人直接 yum install docker-ce,结果装上了一个特别新的版本,然后容器运行的时候各种内核警告、iptables 规则问题,最后不得不降级重装。
Docker 官方仓库里维护着多个版本,CentOS 7 上我推荐使用 docker-ce-20.10.x 这一系列,原因有三:
一是这个版本系列对 CentOS 7 的兼容性经过了长时间验证,无论是 systemd 集成还是 iptables 处理都比较成熟。
二是新版 Docker(比如 24 及以上)对内核和网络组件的要求更高,CentOS 7 的 3.10 内核虽然能跑,但某些高级特性可能无法启用,容易出现诡异的兼容性问题。
三是 Docker Compose 的集成方式在 20.10 之后逐渐从独立的 docker-compose 二进制向 docker compose 插件过渡,20.10 版本里两种方式都保留,对习惯老命令的人更友好。
安装具体版本时,可以先查看仓库里有哪些版本可用:
bash复制yum list docker-ce --showduplicates | sort -r
然后指定版本号安装,注意要用完整的 x.y.z 格式,不要只写主版本号:
bash复制yum install -y docker-ce-20.10.24 docker-ce-cli-20.10.24 containerd.io
这里有一个细节:docker-ce、docker-ce-cli 和 containerd.io 三个包最好保持版本匹配。docker-ce-cli 是客户端工具,containerd.io 是容器运行时,Docker 通过它来真正管理容器生命周期,三者不匹配可能导致 Docker 启动时报 invalid argument 之类的错误。
3. 从零到可用的完整安装步骤
3.1 卸载残留与依赖清理
如果你是一台全新的 CentOS 7 服务器,这一步可以跳过。但如果你之前在机器上试过其他教程、装过一半失败的 Docker,或者系统自带了旧版 docker(比如 docker-engine),那必须先清理干净,否则后面会有一堆莫名其妙的冲突。
清理命令如下:
bash复制yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
执行完 yum remove 后,还要检查一下 /var/lib/docker 目录是否存在。这个目录是 Docker 默认的数据目录,里面存放着所有镜像、容器、卷的数据,如果里面有旧数据,要么删掉,要么备份到其他地方。我这里说的是清理旧环境,不是让你贸然删数据——如果你之前有重要容器数据,先把目录 mv 到备份位置,等新环境跑通后再做数据迁移。
3.2 配置 yum 源并安装 Docker CE
按前面说的,先装基础依赖工具:
bash复制yum install -y yum-utils device-mapper-persistent-data lvm2
然后添加 repo 源。这里我以阿里云镜像站为例:
bash复制yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
添加完源后,可以顺手把 yum 缓存刷新一下,同时安装 Docker:
bash复制yum makecache fast
yum install -y docker-ce-20.10.24 docker-ce-cli-20.10.24 containerd.io
如果你不需要指定版本,直接 yum install -y docker-ce docker-ce-cli containerd.io 也可以,但切记先看看默认装的是不是最新版,以及和你内核是否匹配。
3.3 启动、开机自启与验证
安装完成后,启动 Docker 服务,并设置开机自启:
bash复制systemctl start docker
systemctl enable docker
验证是否安装成功,我习惯用三步走。先看服务状态:
bash复制systemctl status docker
再看客户端和服务端版本信息:
bash复制docker version
最后跑一个 hello-world 容器做实际验证:
bash复制docker run hello-world
这里稍微说一下 docker version 的输出怎么看。客户端(Client)版本和服务端(Server)版本都要有,而且 Server 部分不能报错。如果你看到 Cannot connect to the Docker daemon 之类的提示,说明服务端没起来,先去看 journalctl -u docker 的日志排查原因,别急着跑容器。
4. 镜像下载慢的真相与加速器配置
4.1 为什么默认拉镜像像蜗牛
Docker 装好了,很多人会遇到第一个实际问题:docker pull mysql:8.0 的时候,速度简直让人崩溃,几十 MB 的层能下几个小时,甚至直接超时。
这个问题的根源在于 Docker 默认的镜像仓库在海外,访问速度受网络环境影响很大。Docker Hub 官方镜像仓库虽然全球都有 CDN 节点,但不同地区的实际连接质量差异巨大,从国内直连 Docker Hub,用户体验普遍不理想。
4.2 配置 Registry Mirror 加速器
解决思路和 yum 源一样:给 Docker 配置镜像加速器。所谓镜像加速器,本质上是 Docker Registry 的镜像缓存或代理节点,你从加速器拉取镜像时,实际从加速器的缓存节点获取数据,速度会快很多。
在 /etc/docker/daemon.json 文件中配置 registry-mirrors:
json复制{
"registry-mirrors": [
"https://docker.m.daocloud.io"
]
}
这里我用的是 DaoCloud 提供的公共镜像加速地址,网上还有多家服务商提供的地址,你可以根据自己的网络情况选择,也可以多配几个。配置完保存退出,然后重启 Docker 让配置生效:
bash复制systemctl daemon-reload
systemctl restart docker
验证加速器是否生效:
bash复制docker info | grep -A 1 "Registry Mirrors"
如果能看到你配置的地址,说明加速器已经生效。
4.3 镜像仓库的选择与拉取验证
配置好加速器后,重新拉一次镜像试试速度:
bash复制docker pull mysql:8.0
实测下来,配置加速器之后,拉取速度提升非常明显,几十 MB 的层基本几十秒就能下完。如果你的业务有特殊镜像需求,比如需要从私有仓库拉取镜像,可以在 daemon.json 里加上 insecure-registries 配置:
json复制{
"registry-mirrors": [
"https://docker.m.daocloud.io"
],
"insecure-registries": [
"你的私有仓库地址:5000"
]
}
这个配置是给那些没有启用 HTTPS 的私有镜像仓库用的,配置后 Docker 访问该地址时不会强制校验 HTTPS 证书。
5. 安装 Compose 与常用容器实战:MySQL 8.0、Redis 主从
5.1 Docker Compose 的安装与版本坑
单一容器用 docker run 手动启动还算简单,但一旦涉及多个容器、多个参数,手动启动就非常容易出错。这时候就要用到 Docker Compose,它能用一份 YAML 文件把多个容器的启动配置固定下来,一条命令拉起一整套服务。
CentOS 7 上安装 Docker Compose 有两种方式。第一种是安装 docker compose 插件(需要 Docker 版本支持):
bash复制yum install -y docker-compose-plugin
第二种是下载独立的 docker-compose 二进制文件。第二种方式兼容性更好,不管 Docker 版本新旧都能用,我这边实际用的也是这种方式:
bash复制curl -L "https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ls -l /usr/local/bin/docker-compose
安装完验证一下版本,确保能正常运行:
bash复制docker-compose version
这里有个坑要提醒:网上很多旧教程让你下载 v1.x 版本的 docker-compose,那个版本已经停止维护很久了,有些命令参数和老系统不兼容。直接用 v2 版本比较稳妥。
5.2 MySQL 8.0 容器化部署实战
容器化部署 MySQL 8.0 是我见过最常见的需求。用 Compose 管理比直接 docker run 清晰得多,我先给一份可以直接用的 docker-compose.yml:
yaml复制version: "3.8"
services:
mysql8:
image: mysql:8.0
container_name: mysql8
restart: always
environment:
MYSQL_ROOT_PASSWORD: Root@123456
TZ: Asia/Shanghai
ports:
- "3306:3306"
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
- /data/mysql8/data:/var/lib/mysql
- /data/mysql8/conf:/etc/mysql/conf.d
- /data/mysql8/logs:/var/log/mysql
配置文件写好后,在 docker-compose.yml 所在目录执行:
bash复制docker-compose up -d
这里有几个细节值得展开说。第一,command 参数里指定了字符集为 utf8mb4,这是支持 emoji 和全量中文的基础,MySQL 8.0 默认字符集虽然已经是 utf8mb4,但显式指定更保险。
第二,TZ: Asia/Shanghai 设置时区,避免容器内时间和宿主机不一致。这个坑很隐蔽,如果不设置,默认时区是 UTC,比北京时间慢 8 小时,日志记录、定时任务全都会偏。
第三,数据目录挂载到宿主机的 /data/mysql8/data,这是必须的。如果不挂载,容器一删数据就全没了;挂载后,即使容器重建,数据依然还在。
启动成功后,用客户端连接验证一下:
bash复制mysql -h 127.0.0.1 -P 3306 -uroot -p
连接成功后再查看字符集:
sql复制SHOW VARIABLES LIKE 'character_set_%';
5.3 Redis 主从容器编排示例
Redis 容器化也是高频需求,尤其是主从架构。下面是一个简单的 Redis 主从 Compose 配置:
yaml复制version: "3.8"
services:
redis-master:
image: redis:7
container_name: redis-master
restart: always
command: redis-server --requirepass Redis@123
ports:
- "6379:6379"
volumes:
- /data/redis/master:/data
redis-slave:
image: redis:7
container_name: redis-slave
restart: always
command: redis-server --slaveof redis-master 6379 --masterauth Redis@123
ports:
- "6380:6379"
volumes:
- /data/redis/slave:/data
depends_on:
- redis-master
启动:
bash复制docker-compose up -d
验证主从关系:
bash复制redis-cli -p 6379 -a Redis@123 info replication
看 role:master 和 connected_slaves:1 是否正常。这套配置适合测试环境和小规模业务,生产环境还要考虑哨兵、持久化策略等。
6. 我在 CentOS 7 上装 Docker 踩过的坑
6.1 iptables 被覆盖导致网络异常
这是 CentOS 7 上装 Docker 最常见的坑。Docker 启动时会修改宿主机的 iptables 规则,设置 FORWARD 链、NAT 规则等,这可能导致原来 firewalld 里配置的端口转发、访问控制规则失效。
我遇到的具体情况是这样的:本来服务器上用 firewalld 配置了某个端口只允许内网访问,装完 Docker 后,从外网也能访问这个端口了,因为 Docker 修改了 iptables 规则,把流量转发的规则加到了前面。
遇到这类问题,不要想着去修改 Docker 生成的 iptables 规则,因为容器重启、Docker 重启都会重新生成。更合理的做法是梳理好自己的防火墙需求,用 firewalld 的 rich rule 或者重新规划端口映射策略。
6.2 /var/lib/docker 磁盘暴涨与数据目录迁移
Docker 的数据默认存放在 /var/lib/docker,这个目录和我系统分区分在一起。跑了一段时间容器后,我发现根分区空间告急,一查就是 /var/lib/docker 占了大量空间。
解决方法是在 daemon.json 里配置 data-root,把 Docker 数据目录迁到大磁盘上:
json复制{
"data-root": "/data/docker"
}
配置完重启 Docker:
bash复制systemctl restart docker
注意,修改数据目录时,如果原来 /var/lib/docker 里有数据,需要先手动迁移。稳妥的操作顺序是:先停止 Docker,再 rsync -av /var/lib/docker/ /data/docker/ 复制数据,确认无误后再删掉旧目录,最后修改 daemon.json 并启动 Docker。
6.3 内核版本过低引发的老旧兼容问题
前面提过 CentOS 7 默认内核 3.10 能跑 Docker,但有个别场景会出现兼容问题。比如使用 overlay2 存储驱动时,如果内核版本过低,Docker 可能会报 failed to mount overlay 之类的错误。
遇到这种情况,先确认内核版本:
bash复制uname -r
如果内核版本确实过低,可以考虑升级内核到 3.10 的最新补丁版本(通过 yum update kernel 更新),或者切换到 vfs 存储驱动:
json复制{
"storage-driver": "vfs"
}
不过 vfs 存储驱动性能比较差,不推荐生产环境使用。更合理的做法是升级内核到长期支持版本,但升级内核后要重新验证 Docker 存储驱动是否正常工作。我在实际项目中升级过一次,docker 服务重启后一切正常,这才放心继续用。
最后的几点个人经验
踩了这么多坑,分享几点我的实际体会。
第一,CentOS 7 上装 Docker,与其追求新版本,不如追求稳定版本。docker-ce-20.10.x 是在 CentOS 7 上经过验证的版本。如果你不确定选哪个,就用这个系列的最新补丁版本。
第二,daemon.json 这个配置文件值得花时间认真写。镜像加速器、数据目录、日志大小限制都提前配好,后面会省很多事。比如加上日志滚动配置:
json复制{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
这个配置能防止容器日志无限增长占满磁盘。
第三,安全方面不要省事。root 账户进入容器在生产环境是大忌,尽量用 --user 参数指定运行用户;容器端口不要直接暴露到公网,前面加一层 Nginx 做反向代理更稳妥。
CentOS 7 虽然已经进入生命周期的最后阶段,但在我接触的项目里,它依然在大量生产环境中默默运行。安装 Docker 只是第一步,容器编排、监控、日志、网络这些才是真正要长期经营的课题。希望这篇基于实际操作经验的教程能帮你顺利跨过第一步,后面有任何问题,也欢迎留言交流。
