
在实施岗和运维岗上待久了基本都撞上过这么一件事客户机房做了物理隔离或者生产网络本身就不允许连外网但项目又必须在CentOS 7.9上跑Docker。这时候你手里只有一台裸机、一个U盘想用yum install装Docker根本不好使。我第一次接这种活时也头铁抱着笔记本去现场试着开热点结果发现出口IP全被机房策略挡了最后老老实实走离线安装流程折腾了一下午才把环境盘活。这篇文章就把我后来沉淀下来的CentOS 7.9离线安装Docker的完整过程写出来覆盖从联网机器上拉包、生成依赖列表、拷包传输、本地yum源构建、RPM安装到常用配置和排障照着抄基本能闭眼装完。适合谁看主要是实施工程师、运维开发、以及所有需要在隔离网络或离线环境里交付基础组件的朋友。不管你是在政务网、企业内网还是工控网里干活这篇文章的思路都能直接复用到别的离线软件部署上。内容我把原理和操作都讲透不光是“敲几条命令”就算完事。1. 整体思路离线安装到底在做什么事很多人一听到“离线安装”第一反应是去网上找一个“Docker离线安装包”下载下来然后传到服务器上解压、安装完事。这种思路对Python的pip离线包、Node的大版本tar包可能行得通但放到Docker这种依赖一堆系统组件的软件上就很容易翻车。因为Docker安装包对操作系统有比较严格的依赖关系它要求内核版本、iptables版本、依赖库版本都满足条件随便拿一个“离线包”过来装的时候报一个缺库缺依赖的错就能卡你半天。离线安装的本质其实是“在相同或兼容的系统环境上把安装过程中需要满足的依赖关系提前准备齐全再打包转移”。这里有个适用前提很重要准备环境与目标环境的操作系统版本要一致或者非常接近。我建议两台机器都用CentOS 7.9的对应小版本至少大版本必须一致否则依赖包的兼容性没法保证。整体操作分四条线在一台能联网、系统版本一致的机器上用包管理器把Docker以及它依赖的所有RPM包全部下载到本地形成一个自包含的软件包集合。把这一批RPM包传到目标服务器上放到同一个目录下用createrepo生成本地yum仓库索引。在目标服务器上配置一个指向本地目录的yum源让yum可以基于本地仓库做依赖解析和安装。安装完成之后配置Docker服务参数镜像仓库、存储驱动、自启动等然后做装机验证。这套打法的好处是它完全沿用yum的依赖解析机制而不是人肉去判断“还缺哪个包”。因为yum虽然不联网但它解析依赖、检查冲突的能力还在只要本地仓库里的包是完整的它就能像在线安装一样自动把依赖装好。这也是离线安装里“最不容易出问题”的方案。2. 准备阶段联网机器上抓取RPM包2.1 准备一台“干净的”联网环境联网这台机器我建议是全新的CentOS 7.9最小化安装或者至少保证你还没装过Docker。为什么强调干净因为Docker的RPM包在安装时会识别系统已有组件的版本。如果已经装过旧版Docker用repotrack抓包时yum会认为部分依赖已经满足导致它不会把这些包给抓下来。等你拿这套包去装目标服务器一台干净机器时就会因为缺少依赖而失败。我踩过一次这样的坑在测试机上装了Docker 19.03后又去抓20.10的包结果目标机报缺一堆libseccomp相关的依赖抓下来后一看包列表里果然没有它绕过依赖关系手动补包才救回来。2.2 配置Docker官方yum源以获取最新稳定版在联网机器上先配置Docker官方源。CentOS 7环境下建议用国内镜像源加速官方源在国外拉到一半断流的概率挺大。这里以阿里云镜像源为例# 安装yum-utils提供yum-config-manager工具 yum install -y yum-utils # 添加阿里云Docker CE源 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 将gpgkey地址替换为阿里云地址防止GPG密钥拉取超时 sed -i s/download.docker.com/mirrors.aliyun.com\/docker-ce/g /etc/yum.repos.d/docker-ce.repo配置完以后先跑一次yum makecache确认源可用。这一步如果返回了类似“Docker CE Stable - x86_64”的仓库信息说明源已经通了。我自己一般会顺手把yum缓存也清一下再操作避免之前缓存过旧版本元数据导致抓包不完整。2.3 用repotrack抓取完整依赖链抓包工具我推荐repotrack而不是yumdownloader。两者都能下载RPM包但repotrack会把指定包的所有依赖一并解析并下载yumdownloader默认只下载指定的包除非加--resolve参数而且--resolve对已安装依赖的解析是不彻底的。# 安装repotrack工具 yum install -y yum-utils # 切换到存储目录 mkdir -p /opt/docker-offline-packages cd /opt/docker-offline-packages # 用repotrack下载docker-ce及其全部依赖 repotrack docker-ce执行完以后检查一下目录里的文件数量。Docker 20.10系列在CentOS 7.9上完整依赖链大概在20到30个RPM包左右。如果只下了几个包说明repotrack可能没把依赖解析完全建议用yum deplist docker-ce再确认一遍依赖关系缺什么手动用yumdownloader补。在挑选Docker版本时需要特别提醒一点CentOS 7.9自带的内核是3.10.0-1160而Docker从较新版本开始对内核和iptables的依赖要求变高因此装Docker 20.10算相对稳的选择也是社区里用得最多的“7上Docker版本”。想装更新的大版本比如24.x、25.x在CentOS 7上也往往能装上但遇到兼容性坑的概率会高一些如果不是特别需要新特性我不建议在7.9上追新。2.4 检查关键依赖包是否完整抓完之后我强烈建议先核对三个关键包它们是Docker在CentOS 7上最容易出问题的依赖container-selinux负责容器运行时的SELinux策略支持。这个包如果版本过低或缺失docker-ce安装时会直接报冲突。CentOS 7自带的container-selinux版本往往跟不上需要从源里拉新版本比如2.119.2。repotrack理论上能自动搞定但你最好确认一下它真的存在于目录里。containerd.ioDocker的容器运行时核心组件它跟docker-ce是分开发布的必须保证版本匹配。检查一下目录里containerd.io的版本最好和你要装的docker-ce保持同期比如docker-ce 20.10.24通常配containerd.io 1.6.x。libseccompDocker运行容器时所依赖的系统调用过滤库。CentOS 7.9自带的libseccomp版本偏低如果目标服务器是纯最小化安装这个包一定会缺。怎么快速检查直接ls看文件名或者用rpm -qip查看包版本再对应到docker-ce的依赖需求上。这一步多花两分钟能省掉后面很多麻烦。3. 传输与本地仓库搭建把包变成“能用的yum源”3.1 打包压缩与传输RPM包准备好后把整个目录打包然后传到目标服务器。传输方式有很多内网FTP、SSH scp、U盘拷贝都可以。我个人习惯先用tar压缩再传因为RPM包里有很多小文件直接传几十个小文件SSH往返建立连接的开销比较大压缩成一个tar包后传输速度会快不少也方便校验。# 在联网机器上打包 tar czvf docker-offline-packages.tar.gz /opt/docker-offline-packages # 在目标服务器上解压 tar xzvf docker-offline-packages.tar.gz -C /opt/传完以后别急着下一步。先做两件事1、对比两边的文件数量和总字节大小可以用ls -lR | wc -l和du -sh来粗查确保文件没少。更严谨的是在联网机上用md5sum生成校验清单传到目标机上逐一比对。离线传输偶尔会有文件损坏很多奇怪的报错其实根源就是RPM包坏了这一步避坑价值很高。2、确认目标服务器的系统版本和内核版本。执行cat /etc/redhat-release看系统版本执行uname -r看内核。如果内核比3.10.0-1160还老Docker装上了也可能有运行问题这种情况建议先升级内核再装Docker一般来说CentOS 7.9自带的-1160内核已经能满足Docker 20.10的运行条件。3.2 createrepo生成本地仓库索引包到位后需要让yum能识别这个目录里的包。yum默认不会扫描任意目录下的RPM文件它要求目录必须有repodata索引。createrepo就是用来生成索引的工具。# 安装createrepo工具如果目标机器没有 yum install -y createrepo # 进入包目录 cd /opt/docker-offline-packages # 生成repodata索引 createrepo .执行结束后目录下会多出一个repodata文件夹。注意本地机器上要有createrepo这个工具才能干这件事如果连这个工具也没有可以提前在联网机器上下载它的RPM包一起带过去。createrepo依赖的包不多用yumdownloader --resolve createrepo就可以抓全。3.3 配置本地yum源文件在目标服务器的/etc/yum.repos.d/目录下新建一个仓库文件比如local-docker.repo写入如下内容[local-docker] nameLocal Docker Repo baseurlfile:///opt/docker-offline-packages enabled1 gpgcheck0这里有个重要的细节建议把/usr/bin/createrepo这个文件放在PATH里或者确认执行路径createrepo . 这个命令的“.”指的是当前目录所以一定要先cd到包目录再执行路径写错了后面yum会报“找不到repodata”。另外gpgcheck0这一步是离线环境下的必要妥协RPM包的GPG签名校验在没网的时候基本是没法通过的除非你把公钥也一并带过来导入所以直接关掉校验风险可控。配置完成后执行yum clean all yum makecache如果配置正确yum makecache会显示“local-docker”仓库的元数据缓存成功。到这里目标机器上的yum其实已经具备“本地联机”能力了只是这个“联机”联的是本地硬盘。4. RPM安装与Docker初始化配置4.1 用yum命令完成自动依赖解析安装仓库配置好以后安装就变得异常简单也异常“安全”。yum会自动在本地仓库里解析依赖关系哪个包先装、哪个后装全部由它自己决定不需要我们人工排序。yum install -y docker-ce这条命令会把docker-ce、docker-ce-cli、containerd.io以及所有缺失的依赖一次性装好。如果安装过程中出现了依赖冲突或缺失几乎可以断定是第2步“抓包”环节出了问题比如漏抓了某些依赖包。这时可以回到联网机器上用yum deplist docker-ce把完整依赖打印出来逐一比对本地包目录把缺的包补传过来。安装完成后先不要急着启动先查看一下Docker版本docker --version正常会输出类似“Docker version 20.10.24, build 297e128”的信息。然后执行systemctl status docker看一下服务状态此时通常是“inactive”的还没启动可以继续做配置。4.2 配置镜像加速与关键参数Docker装好后的第一件事一定是配置/etc/docker/daemon.json。这个文件在离线环境里尤其重要因为离线机没法直接访问Docker Hub拉镜像配置镜像仓库可以让你后续用“另一台中转机器拉镜像再导出tar包”的方式工作时更顺手也能保证你在内网自建Harbor仓库后能直接对接。下面是一份在CentOS 7.9上比较稳妥的配置{ exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, storage-driver: overlay2, registry-mirrors: [ https://xxx.mirror.aliyuncs.com ] }逐项解释一下exec-opts里的cgroupdriversystemd是一个实践性很强的选择CentOS 7默认的init进程是systemd让Docker也使用systemd作为cgroup驱动可以让两者的资源管理行为保持一致。如果你以后还要在Docker之上叠加Kubernetes这一项更是标配因为kubelet默认要求Docker使用systemd cgroup驱动。log-driver和log-opts是限制容器日志大小的生产环境必配。不配的话一个日志狂写的容器可以慢慢把磁盘撑满到时候发现服务器“无响应”其实只是/var/lib/docker/containers目录被日志撑爆了。max-size100m、max-file3的意思是单个日志文件100MB最多保留3个超过就滚动清理。storage-driveroverlay2是CentOS 7上最推荐的存储驱动。旧版本Docker默认可能是devicemapper那个方案在CentOS 7上性能差且配置麻烦overlay2是标准做法。配置完daemon.json后重启Docker使配置生效systemctl daemon-reload systemctl restart docker4.3 设置开机自启并验证服务状态离线环境下的服务器往往面临断电重启、机房搬迁等情况。如果Docker没设置开机自启机器重启后所有容器服务都是停的这在生产上是不能接受的。systemctl enable docker然后检查一下自启状态systemctl is-enabled docker输出enabled就对了。接下来做一次完整验证# 查看Docker服务状态 systemctl status docker # 查看Docker系统信息 docker infodocker info输出的内容里有几个关键指标值得特别看一眼Storage Driver是否为overlay2Cgroup Driver是否为systemdDocker Root Dir是否为/var/lib/dockerServer Version是否为刚才安装的版本如果这几项都符合预期Docker安装本身已经成功了。4.4 离线环境下的镜像导入测试离线环境没有公网docker pull这条命令基本是废的。但你可以通过“镜像离线包”的方式把需要的镜像跑起来这里需要先会基本操作在联网机器上docker pull nginx:1.24 docker save -o nginx-1.24.tar nginx:1.24把nginx-1.24.tar传到目标服务器然后执行docker load -i nginx-1.24.tar docker images看到nginx镜像出现在本地列表里就说明Docker的镜像加载通道是通的。接下来可以直接run一个测试容器验证运行链路docker run -d --name test-nginx -p 8080:80 nginx:1.24 curl http://127.0.0.1:8080能返回Nginx欢迎页说明整个Docker运行链路完全正常。5. 内核参数与系统层面的预检查很多人在离线装Docker时只关注RPM包却忽略了内核参数和系统配置层面的准备工作。实际上Docker能不能稳定跑起来内核参数占一半。5.1 检查并启用必要的内核模块Docker依赖网络命名空间、iptables等内核功能CentOS 7.9默认内核一般已经包含了所需模块但有几个模块建议显式加载并设置开机自动加载# 检查模块状态 lsmod | grep -E overlay|br_netfilter # 加载模块 modprobe overlay modprobe br_netfilter其中br_netfilter这个模块很关键它让桥接流量也能经过iptables规则处理是Docker容器网络正常通信的底层基础。如果这个模块没有加载容器可能能启动但外部访问容器端口时会出现连接不通的诡异问题。为了确保重启后模块依然加载可以把它们写进配置文件cat /etc/modules-load.d/docker.conf EOF overlay br_netfilter EOF5.2 调整sysctl内核参数Docker运行需要开启网络转发否则容器只有本机能访问。检查并开启# 临时生效 sysctl -w net.ipv4.ip_forward1 # 永久生效 cat /etc/sysctl.d/docker.conf EOF net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 EOF sysctl --system这里需要提醒的是如果/etc/sysctl.d/docker.conf里的net.bridge.bridge-nf-call-iptables1在sysctl --system时报警告“No such file or directory”那就是br_netfilter模块还没加载成功要先加载模块再执行sysctl。这个顺序别搞反我第一次配置时就是先执行sysctl再加载模块结果那个参数设置一再重启就丢。5.3 确认防火墙策略CentOS 7自带的firewalld默认会拦截大部分流量。离线装Docker时我一般建议按实际需求放行端口而不是直接关防火墙# 放行常用端口 firewall-cmd --permanent --add-port8080/tcp firewall-cmd --reload如果你在隔离内网环境网络策略相对宽松也可以直接停用firewalldsystemctl stop firewalld systemctl disable firewalld但生产环境除非运维规范允许否则不建议这么做。关防火墙省了配置端口的时间却可能把整个Docker主机暴露在风险里不划算。6. 常见问题与排查技巧实录离线安装专属版离线安装Docker的报错类型跟在线安装有一点差别很多问题根源在于前置准备不完整而不是安装过程本身。我把自己遇到过的几类高频问题整理成了排查速查表。现象可能原因解决方法yum install时报“No package docker-ce available”本地yum仓库没配置好或createrepo索引未生成检查/etc/yum.repos.d/local-docker.repo配置确认包目录下有repodata文件夹重新yum makecache安装时报依赖冲突docker-ce与container-selinux冲突抓包时container-selinux版本过低或缺失回联网机重新repotrack或在包目录里补上高版本container-selinux如2.119.2后重新createrepo安装时报“Requires: libseccomp.so.2()(64bit)”目标机器缺libseccomp依赖包从联网机器下载libseccomp的RPM包传到目标机安装后再执行yum install启动时报“iptables failed: iptables --wait -t nat -A DOCKER”系统iptables版本过低或br_netfilter未加载更新iptables、加载br_netfilter模块必要时重启后重新加载模块再启动容器docker info里Storage Driver是devicemapper不是overlay2daemon.json未配置或配置后未重启检查/etc/docker/daemon.json内容systemctl daemon-reload systemctl restart dockerdocker load之后docker images看不到镜像tar包损坏或架构不匹配校验tar包md5确认load时输出的镜像名和tag必要时用docker load -i重新加载容器能启动但外部无法访问端口net.ipv4.ip_forward未开启或firewalld拦截开启ip_forward检查firewall-cmd --list-ports是否放行对应端口服务状态active但docker ps卡住Docker daemon响应异常存储驱动出问题查看journalctl -u docker日志检查磁盘空间df -h必要时重启docker服务6.1 最容易翻车的“RPM包版本不匹配”问题离线安装里真正坑人的往往是版本组合的问题。比如docker-ce 20.10.24要求containerd.io至少是1.6.x而你的离线包里如果混进了一个containerd.io 1.2.xyum在解析依赖时就会报“containerd.io 1.6.0 is needed by docker-ce”这时候傻眼就晚了。解决办法是回到联网机器上用docker-ce的版本依赖显式检查yum deplist docker-ce | grep depend或者更直接的做法用curl查看docker-ce RPM包的依赖定义rpm -qpR docker-ce-*.rpm把输出的依赖包名和版本要求和本地目录里的包逐一比对做到心中有数后再打包传输。6.2 抓包时最容易漏掉的三个包根据我的经验repotrack在CentOS 7.9上抓docker-ce的包最容易漏掉或拉错的是audit-libs-python、libcgroup、policycoreutils-python。这三个包并不是Docker的直接依赖而是container-selinux这个间接依赖包的依赖。repotrack有时候会因为yum缓存或者源数据刷新不及时没有把它们解析进来。如果你在目标机器上遇到了这类缺包报错又不想再折腾回联网机器可以找一个更“暴力”但有效的临时方案把这三个包从7.9的DVD安装镜像就是安装系统时用的那个ISO里直接解压出来。CentOS 7.9的DVD ISO里自带Packages目录包含绝大多数基础RPM包很多离线环境里救急就是靠它。6.3 离线环境如何准备镜像包最后提一句镜像准备的事情。Docker装上之后真正干活肯定还需要各种业务镜像。离线环境下准备镜像的流程是在一台能联网且装了Docker的机器上先pull镜像、打tag、save成tar包再传到离线机上load。需要说明的是这一过程中涉及到的镜像源配置与公网仓库的可访问性取决于实际网络环境在符合网络安全规范的前提下操作即可。要特别注意的是save和export是两回事。save是把整个镜像的层信息、元数据完整打包适合迁移镜像export是把容器的文件系统打包会丢失镜像的历史层信息和标签。离线迁移场景里一定要用docker save和docker load组合别用export和import不然镜像的CMD、ENV这些配置都会丢得七七八八。7. 结束时的一点实操心得装Docker这件事本身不算难尤其在有网的环境下一行yum命令就搞定了。但一旦切到离线环境整个难度会几何级上升因为你失去了“出错了就改、缺什么就现场装”的便捷能力所有准备工作都得在出发前完成。我个人做完这一整套流程后最大的体会是离线安装的成败90%取决于准备阶段做没做细而不是安装阶段手快不快。有几个操作习惯我现在一直保持每次离线部署前都会做一遍第一抓完包后一定打印一份完整的包清单文件名和版本号都列出来随包一起带走。到现场后如果安装遇到问题先对着这份清单检查版本匹配关系能省很多排查时间。第二如果条件允许把CentOS 7.9的DVD ISO也一起带到现场。它不仅是系统的安装介质还是上百个基础RPM包的“应急仓库”离线环境里缺了什么基础依赖包直接mount ISO就能装救急效果一流。第三第一次部署时别怕多跑一遍流程。如果现场时间和条件允许先用一台测试机完整装一遍再上生产比在生产机器上卡壳强一万倍。离线环境里一次“看起来无关紧要的报错”就可能让你抓耳挠腮提前在测试机上跑通流程心里才有底。另外建议把整个离线安装中用到的所有包、配置文件和脚本统一归档放到服务器的固定目录比如/opt/docker-archive。等下次再部署新的离线主机时这套归档可以直接复用不需要重新回联网机器抓包。久而久之你手里会积累出一套覆盖常用软件的离线安装工具包以后的部署速度会越来越快。最后再分享一个小技巧如果目标服务器是VMware虚拟机或者云主机可以在做系统镜像模板的时候就先把Docker装好、配好、打好补丁做成一个“黄金镜像”。后面再交付新环境时直接从这个模板克隆根本不走离线安装流程几分钟就能交付一台Docker-ready的机器。这个方法在批量交付场景下极其好用比反复离线装包高效得多。