前阵子帮某部门同事调试新到的一批CentOS 7服务器,装完系统第一件事就是部署Docker环境。这台机器要跑内部自动化测试的容器集群,时间比较紧,所以我直接按生产标准走了一遍完整流程。这类活儿我干过不少次,每一步都会踩到一些稀奇古怪的坑,比如源配了半天装不上、装完启动直接报错、拉镜像超时到怀疑人生。正好借这个标题,把CentOS 7装Docker的完整链路整理出来,从安装前的环境检查到源配置、组件安装、镜像加速、日常命令、故障排查全部过一遍,适合刚接手服务器的新人运维,也适合准备上容器化但没有完整参考过的开发同学。
1. 安装前的环境检查
很多朋友拿到服务器就直接敲安装命令,装不上才回头找原因。其实这一步花不了几分钟,先把环境搞清楚,后面能省大量时间。
1.1 系统版本与内核确认
CentOS 7本身版本跨度不小,从7.0到7.9都有,不同小版本的系统自带软件包版本差距明显。先确认系统版本:
cat /etc/redhat-release如果显示的是CentOS Linux release 7.x,基本没问题。还要看内核版本,Docker对内核有硬性要求:
uname -rCentOS 7默认内核是3.10.x,这个版本可以跑Docker,但有一个细节要注意:如果你要用overlay2存储驱动,需要内核支持overlay文件系统。CentOS 7自带的3.10内核通常没问题,但部分云主机和精简版系统可能缺少相关模块,这种情况我后面会讲怎么排查。
另外一定要确认系统架构:
arch绝大多数机器是x86_64,但如果碰到ARM架构的服务器,软件源和安装包的选择逻辑完全不同。这一步错一分钱软件源就白配了。
1.2 防火墙与SELinux状态评估
CentOS 7默认开启了firewalld,Docker安装后需要操作iptables规则来实现容器网络和端口映射。如果firewalld和Docker的网络管理逻辑冲突,最典型的现象是端口映射完了从外部访问不到。我的习惯是先把防火墙状态看清楚:
systemctl status firewalld还有SELinux,这个坑在老运维圈里太经典了。CentOS 7默认SELinux是 enforcing 状态,Docker虽然对SELinux有支持,但如果配合某些自定义配置,容器启动的时候会出现权限拒绝的问题。我的建议是:如果对SELinux没有深入了解,先把它改成 permissive 或者 disabled。改法很简单:
sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config setenforce 0注意改完之后最好重启一次,确保配置文件真正生效。我知道有些同事对"关SELinux"有不同意见,但在Docker这个场景下,先关掉或者放宽确实能减少太多莫名其妙的故障。
提示:生产环境如果对安全基线有严格要求,不建议直接disabled,可以保留permissive模式,方便排查权限类问题。
1.3 硬盘分区与数据盘规划
这步新手容易忽略。Docker默认的数据目录是 /var/lib/docker,镜像、容器层、卷数据全在这里。很多服务器的 / 分区就几十G,放几个大镜像就满了,后面再想腾挪就非常被动。
装之前查一下磁盘空间:
df -h如果 / 分区不富裕,提前规划把Docker数据目录放到独立分区或独立数据盘上。改数据目录的方法是在 /etc/docker/daemon.json 里指定:
{ "data-root": "/data/docker" }注意目录要提前建好,比如 mkdir -p /data/docker,然后重启Docker后旧数据不会自动迁移,这一步要在安装完以后马上做。
2. 安装方式对比与选型思路
CentOS 7装Docker有好几条路,我梳理一下各自的适用场景,免得新同学一上来就被各种教程带偏。
2.1 四种主流安装方式
第一是直接执行 yum install docker,这是系统自带的docker包,版本是老旧且不再维护的Docker 1.13,现在新功能一个没有,兼容性还差,不建议用。
第二是使用Docker官方提供的软件仓库安装docker-ce,这是目前最主流的在线安装方式,版本新、升级方便、依赖自动处理干净。
第三是通过官方安装脚本 curl -fsSL https://get.docker.com | bash,这种方式适合临时测试环境,速度确实快,但脚本默认装最新版,不方便锁定版本,而且它有需要联网获取资源的特性,在某些网络受限环境会卡住。
第四是下载RPM包离线安装,适合内网隔离环境。你需要先在一台能联网的机器上把对应架构的RPM包全部下好,然后拷贝进去,用 rpm -ivh 或 yum localinstall 进行安装。缺点是自己解决依赖,麻烦一点。
2.2 选型建议与版本锁定策略
我的建议很简单:能联网的机器一律走官方仓库安装,同时用 yum 的版本锁定功能固定Docker版本。为什么强调锁定版本?因为生产环境经常会出现某个新版本引入坑,导致容器起不来的情况。比如我经历过一次docker-ce小版本升级后带外管理接口的日志狂刷,最后回滚版本才消停。
锁定版本的方法在yum里很简单:
yum install -y yum-plugin-versionlock yum versionlock add docker-ce这样以后 yum update 就不会擅自升级Docker组件。
离线环境则不同,我建议先下载固定版本的RPM包合集。下载的时候记得三个核心包都要拿:docker-ce、docker-ce-cli、containerd.io,三者版本要配套,不能随意混搭。
3. CentOS 7安装Docker完整实操
这一节我按真实环境从头到尾敲一遍命令,每一步都写清楚目的和验证方法。
3.1 清理历史残留
如果这台机器之前装过Docker或者装了一半没装利索,直接再装很可能出现依赖冲突。统一先清理一遍:
yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine这个命令即使没装过也不会报错。同时检查一下是否残留旧的docker组和数据目录:
getent group docker ls -la /var/lib/docker如果 /var/lib/docker 里已有旧数据且不需要保留,直接删掉,否则装完新版本后容器和镜像的历史记录会干扰判断,而且有权限错乱的可能。
3.2 配置软件源并替换为加速地址
先安装需要的依赖工具包,yum-utils 提供 yum-config-manager 命令:
yum install -y yum-utils接着添加Docker官方仓库。这里有一个非常容易出现的问题:默认官方源地址在很多网络环境下访问很慢,repo文件拉下来半天没反应,后面安装环节基本都会超时。所以我的做法是先把repo文件添加好,然后立刻把里面的下载地址替换成本地网络可以稳定访问的镜像站地址。
添加官方仓库:
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo然后编辑 /etc/yum.repos.d/docker-ce.repo,把baseurl里的官方域名替换成你本地的镜像站地址。镜像站的选择很讲究,优先选离你机房近的、带宽充足的,或者你们公司内网自己搭的缓存源。替换时注意保留后面的路径结构,比如 /linux/centos/$releasever/$basearch/stable 这部分别动,只换主机名部分。同时检查一下gpgkey的地址是否也被替换成了对应的镜像站key地址,否则yum会在校验签名时卡住。
仓库文件里通常有多个repo段落,比如stable、test、nightly,生产环境建议只保留stable段,把其他段的 enabled 设为 0。不然一个不小心装了测试版,够你折腾一天。
3.3 安装docker-ce组件并启动服务
源配好以后,先刷新缓存:
yum makecache fast然后安装核心组件:
yum install -y docker-ce docker-ce-cli containerd.io这里解释一下这三个包的关系。docker-ce是Docker服务端核心,负责容器、镜像、网络管理;docker-ce-cli是命令行工具,就是你敲docker命令时调用的客户端;containerd.io是底层的容器运行时,负责真正拉起容器进程。新版Docker按containerd架构做了拆分,这三者必须配套安装。动不动几百MB的下载量,所以源的速度直接决定体验。
安装完成后启动服务并设置开机自启:
systemctl start docker systemctl enable docker启动后先看状态:
systemctl status docker如果看到 active (running) 是最理想的状态。如果看到 failed,先别慌,多数是配置文件的问题或模块加载问题,后面常见问题排查部分会详细说。
3.4 验证安装结果
启动状态正常后,还需要确认版本和关键运行参数:
docker version这个命令会同时输出客户端和服务端的信息,注意看Server部分有没有正常显示。如果Server部分报权限错误,多半是当前用户不在docker用户组里,或者服务没起来。
再确认一下Docker的存储驱动和运行状态:
docker info输出里重点关注 Storage Driver 和 Cgroup Driver 两行,后面配置优化时就用到了。
最后跑一个最经典的连通性验证。这一步其实是在测试能不能从官方镜像仓库拉取镜像并运行容器:
docker run --rm hello-world如果网络没问题,会看到一串提示,说明Docker环境已经能正常拉取镜像并启动容器。如果卡在拉取环节,说明镜像仓库访问不畅,这时候直接上镜像加速配置,也就是下一节的内容。我实测下来,这条命令在裸配环境下经常超时,不代表Docker坏了,只代表没有配置加速。
4. 镜像加速与基础配置优化
Docker装好能用和好用之间还差几步配置。我每次装完必做三件事:镜像加速、存储驱动确认、日志策略限制。
4.1 配置镜像加速器
如果你在生产搞过容器化,一定知道从Docker官方仓库拉镜像有多酸爽。几十M的镜像还好,几个G的系统镜像动不动就卡住。解决办法是配置镜像加速器,也就是让Docker去访问本地网络可达的镜像缓存服务。
Docker的全局配置都在 /etc/docker/daemon.json 文件里,如果这个文件不存在就新建一个,我一般这样写:
{ "registry-mirrors": ["https://<你的加速服务地址>"] }加速服务地址哪里来?一般你用的主流云服务商控制台都会提供专属加速地址,一般来说就是你账号专属的镜像加速域名。如果你公司有自建的镜像仓库,比如用Registry搭建的私有仓库,也可以填自己的仓库地址,注意格式要带https或者http协议头。
改完以后重启Docker:
systemctl daemon-reload systemctl restart docker重启完再 docker info,在输出里能看到 Registry Mirrors 一栏,说明配置已经生效。注意这个文件是json格式,逗号、引号必须标准,少一个逗号整个文件就解析失败,Docker会直接拒绝启动。
4.2 存储驱动与日志限制优化
CentOS 7上Docker默认的存储驱动通常是overlay2,这是目前比较推荐的选择。确认方法:
docker info | grep "Storage Driver"如果显示 overlay2 就放心了。如果显示的是 devicemapper,说明系统没有正确启用overlay支持,这时候需要手动检查:
lsmod | grep overlay modprobe overlay要是内核没有加载对应模块,就需要装对应的内核模块包,或者考虑升级内核。在CentOS 7上还有一种办法是确保 /var/lib/docker 所在分区是xfs文件系统且挂载参数支持overlay,不然也会有问题。
日志限制是我最想强调的一项配置。默认情况下Docker把容器的标准输出日志全量存到json文件里,如果不限制大小,跑个一两天日志文件就能占满整个磁盘。我曾处理过一次线上事故:容器日志把根分区塞满,数据库直接只读不可用。从此我每次装完Docker必配log限制:
{ "registry-mirrors": ["https://<你的加速服务地址>"], "storage-driver": "overlay2", "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" }, "live-restore": true }这里面 exec-opts 配置成 systemd 是为了和系统的Cgroup管理统一。很多用systemd的系统如果这里不设,在容器内看到的内存和CPU会不准确,尤其在Kubernetes环境下会直接导致驱逐误判。log-opts 的max-size设为100m,max-file设为3,意味着单个容器最多保留3个100MB的日志文件,超过后自动滚动覆盖。
live-restore 是针对Docker服务本身重启时的行为,开启后即使Docker服务短暂重启,已经在跑的容器也不会跟着全部停掉,这对生产环境太重要了。改完配置重启Docker,再用:
docker info检查配置项是否生效。有朋友问我 daemon.json 里能不能加 iptables 相关配置,可以,但我一般不动iptables的默认值,让它保持 true 就好,除非你已经完全了解自己在做什么。
5. 日常管理常用操作速查
环境装好以后,日常操作频率最高的那些命令我列一下。
5.1 容器生命周期操作
查看正在运行的容器:
docker ps查看所有容器,包括已经退出的:
docker ps -a容器的状态有几种:Up表示正在运行,Exited表示已经停止,Created表示创建但未启动,Restarting表示在重启中,Paused表示被暂停。如果你经常看到容器反复Restarting,大概率是应用启动就崩溃或者配置有误,需要看日志。
启动、停止、重启容器:
docker start <容器名或ID> docker stop <容器名或ID> docker restart <容器名或ID>进入正在运行的容器调试:
docker exec -it <容器名或ID> bash如果容器里没有bash,可以用 sh。对于容器里没有安装命令调试工具的,可以直接在宿主机上用nsenter进入容器的命名空间,但这种方式比较底层,日常很少用。
删除容器和镜像前确认好,防止误删重要数据:
docker rm -f <容器名或ID> docker rmi <镜像名或ID>docker rm -f 是强制删除,即使容器正在运行也会直接干掉。docker rm -v 是删除容器时同时删除对应的匿名卷,要小心,卷里的数据也将被删除。
5.2 镜像管理与资源查看
拉取镜像:
docker pull <镜像名>:<标签>查看本地已有镜像:
docker images查看镜像历史细节或者容器占用磁盘空间:
docker system df这个命令非常实用,它能列出镜像、容器、卷和构建缓存占用的磁盘空间,是排查"磁盘去哪了"的第一站。
清理无用资源:
docker system prune这个命令会删除所有停止的容器、没有被使用的网络、悬空的镜像和构建缓存。谨慎使用,最好先 docker system df 看看会释放多少空间,再决定动不动。清理时加上 -a 会把所有未被使用的镜像也删掉。
日常挂载目录和端口映射的标准运行示例:
docker run -d --name web-test -p 8080:80 -v /data/html:/usr/share/nginx/html nginx:stable-p 8080:80 表示把宿主机8080端口映射到容器内80端口,-v 是宿主机目录与容器目录的绑定挂载。这两个参数的使用频率极高,映射端口冲突时Docker会直接拒绝启动并提示端口占用,这个坑很常见。
还有一个高频操作是看日志,一般配合行数和时间过滤:
docker logs -f --tail 200 <容器名或ID>-t 参数可以为每条日志加时间戳;--since 10m 可以查看最近10分钟的日志。排查容器崩溃问题的时候,这些参数能快速定位。
6. 高频问题排查实录
最后这一节,我把自己在CentOS 7上装Docker和日常维护中遇到的典型问题整理成速查表,每一类都标注了具体现象、原因和解决路径。
6.1 典型报错与处理方法
| 报错现象 | 可能原因 | 处理方法 |
|---|---|---|
| Cannot connect to the Docker daemon | Docker服务未启动或启动失败 | systemctl start docker,再用 systemctl status docker 看具体错误 |
| 启动失败,提示Error starting daemon | daemon.json配置错误 | 检查json语法,注释多余内容,确认存储驱动和镜像源地址 |
| docker run拉取镜像长时间卡住 | 未配置镜像加速,访问官方仓库不稳定 | 配置accelerator,然后重启Docker |
| device or resource busy | 容器卷挂载未释放 | 重启宿主机,或检查占用进程后重新挂载 |
| iptables: No chain/target/match by that name | Docker网络规则与自建防火墙冲突 | 重启Docker服务,必要时清空iptables规则后重启服务 |
| overlay2: 文件系统不支持 | 文件系统不是xfs或内核模块未加载 | 确认文件系统,加载overlay模块,或改存储驱动 |
| chown: invalid argument | 数据卷目录权限异常 | 检查目录权限和SELinux状态 |
| docker-compose命令找不到 | 只装了docker-ce,未安装compose插件 | 安装docker-compose-plugin包或用独立二进制文件 |
6.2 排查思路与避坑心得
做一个故障排查的基本流程:先用 systemctl status docker 确认服务层面状态,再用 journalctl -u docker 看日志尾部错误,最后用 docker info 检查配置还原情况。大多数启动类问题都能在日志里直接看到原因,别一上来就重装系统。
多次实操下来,我最大的感受是:CentOS 7上Docker装不好,十有八九是源和镜像加速的问题,其次是daemon.json写错导致服务起不来。yum源配好后先执行 yum list docker-ce --showduplicates 确认能看到版本列表,这一步能提前发现仓库地址不对的问题。替换镜像源的时候特别要注意后面路径的 $releasever 变量,7这个数字如果被替换掉了,yum可能拉不到任何包。另外,给生产环境装完Docker后记得跑一轮容器网络测试,先起一个临时容器验证端口映射、域名解析、容器间互通是否正常,别等业务挂上去才发现网络不通。
最后再分享一个小技巧:如果你有大批CentOS 7机器要统一装Docker,别一台一台手动敲命令。选一台干净的基础机器,把配置好的 /etc/docker/daemon.json 和 /etc/yum.repos.d/docker-ce.repo 保存下来,然后写个几十行的shell脚本批量推送再执行。脚本里面加一个幂等判断,即已经装过且版本一致的自动跳过,这样整个几十台集群的初始化就能从半天压缩到十分钟以内。这不仅省时间,更关键的是能保证每台机器的环境一致性,后面出问题排查起来会少很多变量。