ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CentOS 7安装Docker CE完整教程:环境检查、配置优化与排错实战

CentOS 7安装Docker CE完整教程:环境检查、配置优化与排错实战 前两天给一台旧服务器部署环境系统是CentOS 7.9要在上面把Docker跑起来。说实话这个活不复杂但实际操作时发现网上教程要么是照抄官方文档没把CentOS 7特有的坑说出来要么是版本太老还停留在docker 1.13时代。整个流程走下来我遇到了graphdriver权限问题、iptables链冲突、镜像拉取超时等一系列状况把排查过程理顺后觉得有必要写一篇真正面向CentOS 7安装Docker的完整教程。这篇内容面向谁如果你正准备在CentOS 7上从零安装Docker CE或者在安装过程中已经碰到报错不知道从哪下手又或者装完之后想搞清楚daemon.json、cgroup驱动、镜像加速这些配置到底该怎么设那这篇文章适合你。只装一遍的人可能看不出价值但凡是以后还要在CentOS 7上重复部署环境、批量装机的这套流程能帮你少走不少弯路。1. 动手之前先确认CentOS 7装Docker的三个大前提很多人拿到服务器就急着执行安装命令结果报错了才回头查环境。实际上CentOS 7上装Docker本身不难难点在于环境是否满足Docker的运行要求。我建议动手之前先把下面这几项过一遍最多花五分钟后面能省下半小时排错时间。1.1 系统版本、内核与架构怎么查Docker要求Linux内核版本不低于3.10CentOS 7默认内核是3.10.0-xxx理论上都满足条件但部分云镜像或精简版系统内核打了补丁或做了裁剪可能导致cgroup或namespace功能不完整。先执行这几条命令确认基础信息cat /etc/redhat-release uname -r uname -m第一个命令确认系统版本第二个看内核版本第三个看CPU架构。如果输出x86_64后面用x86_64的rpm包如果是aarch64需要找ARM版本的镜像源。另外用df -h /var确认磁盘空间Docker程序本身大概占几百MB但镜像和容器数据都在/var/lib/docker下生产环境建议给这个目录预留充足空间。这里补充一个很多人忽略的点Ubuntu下Docker要求内核版本高于某个值但CentOS 7官方文档的说法是3.10或更高即可我实际测试过3.10.0-1127以前的老内核跑新版Docker 24.0偶尔会出现容器网络异常稳妥起见尽量把内核升级到3.10.0-1160或更高版本。关于内核升级这里不展开但如果你装完Docker后遇到奇怪问题先怀疑内核版本是个不错的排查方向。1.2 存储驱动与文件系统的兼容性Docker默认推荐存储驱动是overlay2但overlay2在xfs文件系统上有个硬性要求必须支持d_type特性。CentOS 7默认用xfs格式化根分区正常情况下是支持d_type的但有些云服务商在制作镜像时用了-n ftype0参数格式化这就导致Docker启动时报permission denied或者storage-driver相关错误。检查方法xfs_info / | grep ftype如果返回ftype1说明没问题如果是ftype0overlay2用不了只能换用vfs或使用ext4分区。vfs性能很差我建议这种情况把/var/lib/docker挂载到一个ext4分区或者重新格式化xfs时加上-n ftype1。还有一个必须面对的问题SELinux。CentOS 7默认开启SELinuxDocker对SELinux的支持是有的但配置不当会报各种权限错误。如果你不熟悉SELinux策略配置可以先执行getenforce看看状态如果是Enforcing安装过程中报权限问题的概率会大不少。临时验证可以用setenforce 0确认是SELinux导致的问题后再决定是否永久关闭或者配置正确的策略。1.3 为什么不用CentOS 7自带的docker包CentOS 7的extras软件源里有一个docker包版本是1.13。这个是老古董了命令行参数、存储驱动、网络方案和现在的Docker CE差异很大很多新镜像跑不起来。yum install docker 装完之后你可能还要手动装docker-compose之类的东西完全是浪费时间。所以我强烈建议安装Docker CE不要用系统自带的旧包。Docker CE的官方仓库是download.docker.com但在国内直连速度不稳定很多时候yum拉包特别慢甚至超时。解决办法是用阿里云镜像源地址是https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo阿里云这个repo会同步Docker CE官方仓库的rpm包版本全、速度快而且不需要额外注册。如果你在内网环境也可以自己搭一个yum源这个在后面离线安装部分单独说。2. 主推方案阿里云yum源安装Docker CE的完整流程环境确认没问题之后接下来是正式的安装流程。这套流程我在多台CentOS 7.6和7.9上验证过从yum源配置到docker run hello-world跑通大概五分钟内能完成。2.1 清理历史残留版本如果这台机器以前装过docker或者docker-engine先清理干净否则新旧文件混在一起容易出莫名其妙的问题。执行yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine这条命令会把常见的旧Docker组件全部卸载。如果提示没有安装这些包直接忽略即可。另外检查一下/var/lib/docker目录是否存在如果存在且你确定里面的旧数据不用了可以rm -rf /var/lib/docker注意这个操作不可逆确认清楚再删。2.2 添加yum源并更新缓存先装依赖工具yum install -y yum-utils device-mapper-persistent-data lvm2yum-utils提供yum-config-manager命令device-mapper-persistent-data和lvm2是Docker存储驱动相关依赖装上有备无患。接下来添加阿里云Docker CE源yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo这条命令会把阿里云的repo写入/etc/yum.repos.d/下。添加完成后建议打开repo文件核对一下路径确认baseurl指向的是$releasever而不是写死的版本号避免以后升级系统后源失效。然后更新缓存yum makecache fast如果是新装的系统yum源本身需要一点时间初始化耐心等它跑完。2.3 安装docker-ce并启动直接装最新版本yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这里多说一句新版Docker把docker-ce-cli、containerd.io拆成了独立包不安装的话docker命令行和容器运行时都会缺东西。docker-buildx-plugin是BuildKit的构建插件docker-compose-plugin是Docker Compose v2插件这两个不是必须的但我建议装上后面构建镜像和编排容器用得上。安装完成后启动服务并设置开机自启systemctl start docker systemctl enable docker然后验证docker version分别查看Client和Server部分Server出现说明daemon已经正常运行。接着跑一个最经典的验证docker run hello-world如果你看到Hello from Docker!说明整条链路都是通的。如果这一步卡在镜像拉取大概率是Docker Hub网络问题后面第5部分会讲镜像加速的配置。2.4 指定版本安装与yum自动升级的权衡默认的yum install docker-ce装的是当前最新版本而且以后执行yum update时Docker也会跟着升级。这在大版本升级时可能带来兼容性风险所以生产环境我强烈建议指定版本安装。查看仓库里有哪些版本yum list docker-ce --showduplicates | sort -r输出结果里会列出所有可用的docker-ce版本比如docker-ce-3:20.10.24-3.el7或者docker-ce-3:24.0.9-1.el7这种格式。安装指定版本的命令是yum install -y docker-ce-20.10.24 docker-ce-cli-20.10.24注意docker-ce和docker-ce-cli的版本要一致containerd.io单独装最新版即可。我自己在CentOS 7上用的最多的是20.10系列这个版本在CentOS 7上验证最充分稳定性好碰到坑也好搜解决方案。24.0系列在CentOS 7上也能跑但有些内核版本配合不顺畅。对了如果你希望Docker固定版本不被yum update误升级可以在yum配置文件/etc/yum.conf里加一行excludedocker-ce*这样yum更新时会跳过Docker相关包后续手动指定版本升级。3. 其他安装路径脚本安装和离线rpm安装的真实体验yum源安装是最常规的方式但还有两种场景会用到其他方案一是图省事用官方脚本二是内网环境无法联网。这两个我都实际用过各自的坑说清楚。3.1 官方get.docker.com脚本适合什么场景官方提供了一个一键安装脚本命令是curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh --mirror Aliyun这个脚本的本质是自动完成添加yum源、安装docker-ce-ce、启动服务这些步骤用一个命令代替手动操作。脚本可以在安装时指定--version参数例如--version 20.10。适合的场景是临时测试环境、快速搭建一个Docker环境验证想法的时候用。但我为什么不推荐在正式环境用原因有两个第一版本不够可控如果你不显式指定版本脚本只会告诉你最新版安装完成至于装的是哪个小版本你要自己去查第二脚本运行时需要联网下载而且对一些已经有了旧版本Docker、或者系统做了特殊配置比如自定义了yum源的机器脚本的处理逻辑不一定符合你的预期。有时候脚本装完docker-compose-plugin没有一起安装你还得手动补一步。所以我的建议是脚本安装用于个人玩一玩可以正式服务器老老实实走yum源流程也就多了三条命令。3.2 内网环境离线安装的完整做法很多生产环境是内网隔离的这时候需要在一台能联网的同系统、同架构机器上把rpm包下载下来再拷到内网安装。外网机器上执行mkdir -p /tmp/docker-ce yum install --downloadonly --downloaddir/tmp/docker-ce docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin执行完检查/tmp/docker-ce目录会看到一堆rpm文件把它们打包拷到内网机器上。内网机器上安装cd /tmp/docker-ce yum localinstall *.rpmyum localinstall会自动解析依赖关系如果内网yum源里缺少依赖包它会提示缺失这时候只能手动补rpm。常见的坑是container-selinux这个包它不在Docker仓库里而是来自CentOS base源内网机器如果yum源不完整就会卡在这。解决办法是外网下载container-selinux后一起拷过去。另一个需要注意的坑是rpm包的架构必须一致x86_64的rpm不能装到aarch64机器上。批量给多台机器部署的时候我建议先在一台机器上装好并测试通过然后把rpm包目录和安装脚本固化下来下次直接脚本化操作效率高很多。4. 装完先别急着跑容器这几个配置决定后面省不省心我见过太多人装完Docker直接docker run一个nginx就开始测等真正业务跑起来才发现日志文件无限增长、普通用户没有权限、cgroup驱动和k8s不匹配等问题。这些配置在装完Docker那一刻就该一次性设好。4.1 daemon.json的推荐配置Docker守护进程的核心配置在/etc/docker/daemon.json这个文件默认不存在需要自己创建。我常用的推荐配置{ exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, storage-driver: overlay2, registry-mirrors: [https://你的ID.mirror.aliyuncs.com] }四个关键项分别说明。exec-opts把cgroup驱动改为systemd如果只是跑普通容器默认的cgroupfs也能用但如果你之后要装kubeadm跑Kuberneteskubelet要求cgroup驱动必须一致再用cgroupfs就会报failed to run Kubelet的错误。提前设成systemd等于给未来留好路。log-driver和log-opts控制日志轮转容器日志默认不限制大小一个容器跑上几个月能写出几十GB日志把max-size和max-file配好能避免磁盘被日志写满。storage-driver指定overlay2。registry-mirrors是镜像加速地址阿里云容器镜像服务控制台可以免费申请一个专属加速地址格式类似https://xxxx.mirror.aliyuncs.com这个地址需要按自己的账号申请直接复制别人的不一定能用。配置完执行systemctl restart docker然后docker info查看输出的Storage Driver和Registry Mirrors两栏确认配置已经生效。4.2 普通用户免sudo操作DockerDocker默认只有root用户能操作因为docker socket文件/var/run/docker.sock的属主是root。每次加sudo太麻烦而且有些脚本在sudo和非sudo环境下环境变量不一致容易出问题。把日常用户加入docker组是标准做法usermod -aG docker $USER然后重新登录会话或者执行newgrp docker让组权限生效。验证方式是直接执行docker ps不用sudo也能看到输出。但这里必须说一句大实话加入docker组的用户等同于拥有root权限因为docker支持把宿主机目录挂载进容器某人在容器里挂载整个根目录就能修改宿主机文件。所以docker组只能加给你信任的用户别图省事给所有人加。4.3 开机自启与文件描述符限制开机自启这个不用多说systemctl enable docker如果机器上跑了很多容器每个容器都会占用文件描述符系统默认的ulimit可能不够用。出现too many open files之类的报错时在daemon.json里加default-ulimits: { nofile: { Name: nofile, Hard: 1048576, Soft: 1048576 } }重启Docker后生效。4.4 Docker Compose怎么装新版Docker CE通过docker-compose-plugin插件提供Compose功能安装命令就是前面提到的一起安装那个包。装好后执行docker compose version如果输出正常说明Compose v2已经就绪用法是docker compose up -d注意中间有个空格不是旧版横杠的docker-compose。有些教程还会让你从GitHub下载docker-compose二进制放到/usr/local/bin里这是老方法了在CentOS 7上没有必要再用。除非你用的是10年前的老版本Docker否则直接用插件就好。5. 安装过程中最常踩的五个坑完整排查链路这个章节是全文的重点。我把CentOS 7上装Docker经常遇到的五个问题按排查链路写出来你照着这个顺序查比自己盲目搜报错信息效率高得多。5.1 启动daemon报错graphdriver permission denied表现执行systemctl start docker之后用systemctl status docker看到服务一直在重启运行journalctl -u docker -n 50查看日志里面出现类似error initializing graphdriver: permission denied的报错。排查链路第一步查看/var/lib/docker目录的属主和权限正常应该是root所有如果你手动chown过其他用户先改回来ls -ld /var/lib/docker第二步查看SELinux状态getenforce如果输出Enforcing尝试临时关闭SELinux验证setenforce 0 systemctl restart docker如果这样能正常启动说明就是SELinux策略的问题。接下来有两种选择临时方案是继续保持SELinux关闭状态但重启后SELinux会重新启用所以需要修改/etc/selinux/config把SELINUX改成disabled或者permissive正规方案是安装docker-selinux策略包并正确配置但这个复杂度高一些。我个人在CentOS 7上做生产环境时如果业务没有强制等保要求我一般建议关闭SELinux但前提是安全由防火墙和权限管理承担。这一步你现在决定别等到排错时再做。5.2 容器网络不通与iptables链冲突表现镜像能启动但在容器内ping 8.8.8.8或者ping www.baidu.com不通宿主机网络正常重启了几个容器也不管用。排查链路先看宿主机防火墙状态systemctl status firewalld如果firewalld是运行状态再执行iptables -t nat -L -n | grep DOCKER如果看不到DOCKER链或者iptables里docker相关规则被清掉了大概率是firewalld重启时把Docker写入的iptables链清掉了Docker又没有重新生成。最常见的场景是Docker启动时firewalld还没起来后来firewalld重启覆盖了iptables规则导致Docker的NAT规则丢失。解决办法是重启Docker让iptables规则重新生成systemctl restart docker如果反复出现这种情况可以考虑停用firewalldsystemctl stop firewalld systemctl disable firewalld或者反过来不用firewalld改用iptables服务。我的建议很简单生产环境网络规划里选一个防火墙方案别两个并存这是容器网络出问题最普遍的根源。5.3 Cannot connect to the Docker daemon的排查顺序这条报错是新手最常遇到的docker ps执行后直接提示Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?正确排查顺序是按下面四步走systemctl status docker ps -ef | grep dockerd ls -l /var/run/docker.sock journalctl -u docker -n 50先看服务状态如果服务是active (running)再确认dockerd进程是否存在如果进程存在检查socket文件是否存在如果以上都正常看日志里有没有报错。最常见的两个隐藏原因第一是daemon.json语法错误比如JSON里多了一个逗号或者写错了字段导致dockerd启动时直接退出第二是磁盘满了Docker写日志写不进去同样启动失败。journalctl里会看到no space left on device之类的明确提示。另外如果docker ps提示socket权限拒绝但服务和进程都正常执行ls -l /var/run/docker.sock看socket属主和权限然后把你当前用户加入docker组或者临时用sudo验证。5.4 镜像拉取超时与registry mirror配置前面docker run hello-world卡住或者提示net/http: TLS handshake timeout问题出在访问Docker Hub公网镜像站不稳定不是Docker本身的问题。最常见方案是配置registry mirror镜像加速。上一节daemon.json里已经写了registry-mirrors字段配置完后systemctl restart docker用docker info查看Registry Mirrors是否已经生效。测试拉取一个镜像docker pull nginx:alpine如果加速配置正常拉取速度会有明显提升。补充说一下镜像加速只对Docker Hub的镜像有效如果是从其他私有仓库或者第三方仓库拉取那是另一套配置这里不展开。5.5 内核模块缺失导致容器无网络如果iptables没问题、firewalld也正常但容器内就是无法访问外网很可能是内核没有加载br_netfilter模块。CentOS 7的纯净镜像尤其是云镜像经常出现这个问题。手动加载并验证modprobe br_netfilter sysctl -w net.bridge.bridge-nf-call-iptables1然后执行lsmod | grep br_netfilter确认模块已加载。为了让重启后仍然生效写进系统配置echo modprobe br_netfilter /etc/rc.local chmod x /etc/rc.local同时把sysctl参数写入/etc/sysctl.confcat /etc/sysctl.conf EOF net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 EOF sysctl -p这也是很多人容器无法上外网但查了半天防火墙都没发现问题的根源所在。6. Docker升级与卸载数据安全比命令本身更重要Docker用的时间长了总会有升级或卸载的需求。这一步操作不要马虎因为镜像、容器、数据卷都保存在/var/lib/docker里一个命令敲错数据就没了。6.1 升级Docker版本的正确顺序升级前先停服务这是大前提systemctl stop docker然后备份配置目录cp -r /etc/docker /etc/docker.bak.$(date %F)数据目录/var/lib/docker如果空间充足最好也做一个简单备份或者快照。对于生产环境我习惯用tar打包或者云硬盘快照的方式因为一旦跨大版本升级后容器起不来还能回滚。接下来用yum安装目标版本yum install -y docker-ce-新版本 docker-ce-cli-新版本升级完成后启动Docker重点检查两件事docker version显示的服务端版本是否符合预期docker ps -a列表里的容器是否还在。容器没有消失是因为Docker默认不会删除/var/lib/docker数据但如果跨了多个大版本比如从17.03直接升到24.0容器元数据格式不兼容docker ps -a可能看不到容器这个比较棘手。所以生产环境升级前务必确认版本跨度尽量在同一大版本内升级比如20.10.x小版本升级风险要小得多。6.2 彻底卸载需要清理哪些文件卸载Docker程序和卸载Docker数据是两回事。程序的卸载yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这条命令不会删/var/lib/docker不会删/etc/docker。如果你只是想换个版本重装保留这些数据是好事新版本Docker启动后会自动读取。如果你确定这台机器不再需要Docker或者要把环境彻底重置手动清理rm -rf /var/lib/docker rm -rf /etc/docker清理之前记住/var/lib/docker下面有所有容器的镜像层、容器层、数据卷、网络配置删掉就彻底没了没有任何恢复手段。我曾经见过有人为了释放磁盘空间随手执行rm -rf /var/lib/docker想清掉无用镜像结果把另一个项目组的数据库数据卷也一起删了场面相当惨烈。判断清楚这个目录下的内容和影响范围再执行删除命令。最后再说说我在CentOS 7上使用Docker的个人体会这套系统虽然已经停止主流维护但在存量服务器里占比依然不小Docker在7上的运行稳定性经过多年验证反而比很多新系统更让人放心。我的常规做法是一台新CentOS 7环境先花三分钟检查内核、文件系统和SELinux状态然后用阿里云源装好20.10版本的Docker CEdaemon.json一次性配置到位后续几乎不用再管Docker本身的事只需要关心业务容器。如果你也打算在CentOS 7上装Docker按着这个流程走一遍应该能避开大多数常见的坑。
返回列表