尧图精选

完全离线安装Docker:rpm包制作、依赖处理与配置启动全攻略

🕒 发布时间:2026/9/18 23:00:15 📁 来源:尧图网络
1. 项目背景与整体思路1.1 为什么需要离线安装Docker在开始之前先聊聊我为什么会碰这个事。早期我在维护几台生产服务器的时候发现一个很常见的问题服务器在内网环境物理隔绝外网但业务部门又急需用Docker跑容器化应用。你没法在那种环境里执行yum install docker或者apt install docker.io因为源头仓库根本连不上。这种场景在很多行业里非常常见——政企内网、军工涉密网、金融核心机房、校园实验室甚至某些云厂商的专有云区域管控网络与公网完全隔离。这时候离线安装Docker就成了唯一解。你把安装包下载好拷进去解压配置启动整个过程不需要外网只需要你手上有正确的离线包和依赖。很多新手一听到离线安装就头大觉得没有网络什么都做不了。实际上Docker的离线安装逻辑非常清晰把所有需要的二进制文件和依赖一次性准备好剩下的就是在目标机器上把它们放到正确的位置并启动服务。理解了这一点你就能举一反三离线装Kubernetes、离线装Node.js、离线装MySQL思路全部通用。1.2 本项目的适用范围与核心目标这篇博文面向的是需要在完全离线或半离线环境下部署Docker的朋友。不管你是运维工程师、开发工程师还是刚接触Docker的实验室管理员这篇文章都能帮到你。我们用的目标环境是CentOS 7.x系列这应该是国内服务器存量市场上最常见、也最容易被要求做离线部署的操作系统版本。Docker官方支持CentOS 7但CentOS 7内置的yum源在默认情况下指向的是官方镜像仓库离线环境根本用不上。所以我们的方案是在有网的机器上下载Docker的rpm离线包及其全部依赖将离线包复制到目标机器用rpm命令本地安装配置Docker服务参数启动并验证环境配置开机自启动这套流程全程不需要外网完全可控而且目标机器上不依赖任何第三方源的配置改动。整个过程如果你熟练大概十分钟可以完成但我会把每个细节都展开讲清楚包括你可能会踩的坑。2. 环境准备与依赖分析2.1 确认目标机器系统版本与内核在下载离线包之前先要在目标机器上确认两个关键信息操作系统发行版本和内核版本。这两个决定了你该下哪个版本的Docker包。cat /etc/redhat-release这个命令在CentOS上会输出类似CentOS Linux release 7.9.2009 (Core)的信息。这里要确认是7.x版本因为Docker官方针对RHEL/CentOS 7和8分别提供不同的rpm包。另外执行uname -r确认内核版本。Docker 20.10及以上版本要求内核版本在3.10以上CentOS 7默认内核是3.10.0系列满足要求。但如果你的机器内核过于老旧比如3.10.0-327可能需要考虑升级内核否则Docker的overlay2存储驱动可能工作不稳定。小提示很多人在这一步会忽略内核版本。实际上我遇到过一台老机器内核恰好在3.10.0-514以下Docker启动时overlay2支持有问题最后只能改成vfs驱动凑合用性能差了不少。所以内核检查别跳过。2.2 检查依赖软件是否齐全虽然我们用rpm离线安装依赖问题大部分由rpm包管理器自动处理但有一些基础工具如果缺失安装过程中会报错很难看。建议先执行rpm -qa | grep -E libcgroup|libseccomp|iptables如果你发现libseccomp没装建议一并下载离线包。这个库是容器运行时的安全隔离基础负责系统调用的过滤没有它Docker守护进程可能无法正常启动。同样的iptables也是Docker网络功能依赖的核心组件NAT规则和端口映射全靠它。还有一项容易被忽略的是device-mapper-libs虽然现在默认存储驱动是overlay2但某些场景下系统仍然会调用device-mapper相关的库。为了保险起见把这些基础依赖一并放到离线包里。2.3 确认网络环境类型全离线还是半离线在实际项目中我一般会把离线分成两种情况分别处理全离线目标机器没有任何外网连接yum源也用不了只能把rpm包用U盘/跳板机拷贝进去。半离线目标机器能连接内网的yum源比如本地的CentOS镜像仓库但不能连外网。这两种环境的处理方式不一样。半离线可以直接修改yum源指向内网镜像然后yum install docker全离线则必须走rpm离线安装。我们的教程重点讲全离线。但即使你是半离线环境这套方法同样适用因为rpm本地安装不依赖yum源是否可用。3. 离线包获取与准备3.1 下载Docker的rpm离线包这一步需要一台可以访问外网的机器系统最好也保持CentOS 7这样下载的依赖才不会有版本兼容问题。你可以用一台临时的云服务器或者你自己办公电脑上的虚拟机。推荐用Docker官方仓库的rpm包地址。Docker官方将RHEL/CentOS的仓库配置为https://download.docker.com/linux/centos/7/x86_64/stable/Packages/。有两种下载方式第一种直接浏览器访问上面的地址把需要的rpm包手动下载。这种方式适合只需要下载个别包的情况。但依赖关系就麻烦了需要自己一个个对照很容易漏。第二种用yumdownloader工具自动下载指定包及其全部依赖这是我最推荐的方式。在有网的机器上先安装yum-utilsyum install -y yum-utils然后添加Docker官方仓库yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo接着新建一个目录存放离线包执行下载命令mkdir -p /opt/docker-offline cd /opt/docker-offline yumdownloader --resolve docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin重点解释一下每个包的作用docker-ceDocker守护进程主程序dockerd整个Docker的核心。docker-ce-cli命令行客户端工具也就是你平时敲的docker命令。containerd.io容器运行时管理组件负责实际创建和运行容器是dockerd与容器之间的桥梁。docker-buildx-plugin构建镜像的BuildKit插件没有它新版Docker在构建镜像时会提示找不到buildx。docker-compose-plugin用于支持docker compose命令如果你后面要编排多容器应用这个必须装。--resolve参数是关键。它会自动解析依赖关系把docker-ce所有依赖的rpm包全部下载到本地目录。下载完成后检查目录内容ls -lh /opt/docker-offline你能看到一堆rpm包包括之前提过的libseccomp、container-selinux、iptables等依赖。把这些全部打包cd /opt tar czf docker-offline.tar.gz docker-offline然后把这个tar包通过U盘、scp跳板或者任何你能用的方式拷贝到目标离线机器上。3.2 获取依赖的通用方法论除了Docker本身建议你在有网的机器上把下面这些工具也一并准备好因为它们在内网环境经常被用到而且也不一定能随时再拿到socat主要用于端口转发和容器网络调试git拉取代码用telnet / nc网络排查工具vim文本编辑工具下载方法完全一样还是yumdownloader --resolve。这种方法论的核心价值在于你的/opt/docker-offline目录就是一个可重复利用的离线软件包仓库。我通常会把不同版本的Docker离线包按版本号分目录保存例如docker-offline-20.10.24/、docker-offline-24.0.7/这样后续复用时直接拿对应版本不用重新下载。3.3 联网机器与目标机器系统版本不一致时的处理有时候你手头可以联网的机器是CentOS 8但目标机器是CentOS 7。这时候直接用CentOS 8下载的rpm包去装CentOS 7大概率会出现依赖版本过高、GLIBC版本不兼容的问题。我建议严格保持相同大版本、相同架构。架构方面尤其要注意。x86_64的包不能装在arm64的机器上比如飞腾、鲲鹏、龙芯这样的国产芯片平台。这些平台的Docker安装包通常需要去对应厂商的仓库或者Docker官方arm64目录下找。判断目标机器架构uname -m输出x86_64就是标准的Intel/AMD架构输出aarch64就是ARM架构。一旦架构不对安装时会立刻报wrong ELF class之类的错误完全没法用。4. 安装步骤与核心操作4.1 解压离线包并执行本地安装将tar包拷贝到目标机器后找个合适的目录解压。我一般习惯放在/opt下方便记录和管理。cd /opt tar zxf docker-offline.tar.gz cd docker-offline现在目录下有一堆rpm包。安装有两种方式第一种用yum localinstall它会扫描当前目录的rpm包作为本地源自动解决依赖。但这种方式要求系统已经配置了可用的yum源如果没有源它可能会报错。第二种用rpm -ivh加通配符强制本地安装这是全离线环境最可靠的方式rpm -ivh *.rpm执行后你会看到系统逐个安装rpm包的输出。如果遇到依赖缺失rpm命令会明确告诉你缺哪个包你回到有网机器下载缺失的包再补装就行。如果你遇到已存在的同名包可以加参数--replacepkgs强制覆盖安装。如果你只想缺什么装什么也可以在前面不把containerd.io放进去先装其他包最后用rpm -ivh containerd.io-1.6.*.rpm单独安装灵活处理。实操经验rpm -ivh *.rpm在包数量很多的情况下偶尔会因为依赖顺序问题报错。更稳妥的方式是用rpm -Uvh *.rpm升级安装模式宽容度更高即使有些包之前装过低版本也能识别处理。不过可能报package ... is already installed这种直接忽略即可。4.2 验证Docker二进制文件是否可用安装完成后先别急着启动做两个快速验证。验证命令行工具docker --version正常情况下会输出Docker版本号比如Docker version 24.0.7, build afdd53b。验证守护进程二进制文件存在which dockerd ls -l /usr/bin/dockerd如果docker命令能找到说明CLI装好了。如果dockerd找不到很可能master程序没装完整回头检查docker-ce包是否安装成功。4.3 创建Docker配置文件并配置镜像加速Docker安装完成后默认配置文件在/etc/docker/daemon.json但这个文件默认是不存在的需要你手动创建。mkdir -p /etc/docker cat /etc/docker/daemon.json EOF { exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, storage-driver: overlay2, registry-mirrors: [https://your-mirror.example.com] } EOF每个配置项的解释exec-opts决定容器资源管理的cgroup驱动方式。使用systemd是Cgroup根目录下统一管理的最佳实践特别是以后你要在Docker之上跑Kubernetes集群这一项必须提前配好否则kubelet会报警告。log-driver与log-opts限制容器日志文件的大小和数量防止容器长时间运行把磁盘写爆。max-size100m表示单个日志文件最大100MBmax-file3表示最多保留3个文件。这是我在生产环境中的标配曾经因为没配日志轮转一个容器把200GB数据盘写满从那以后我每次都加。storage-driver存储驱动overlay2是目前Linux上的最佳实践性能好、支持层式文件系统。registry-mirrors镜像加速器地址。如果你在离线环境下有自己的Harbor私有仓库可以填内网地址如果你在测试环境里可以暂时不填等以后需要拉取镜像时再通过其他方式导入。4.4 启动Docker服务配置文件搞定后加载并启动Dockersystemctl daemon-reload systemctl start docker检查启动状态systemctl status docker如果看到绿色的active (running)说明Docker启动成功。但是别高兴太早有一个坑我总结过多次systemctl start docker报错的时候很多人第一反应是看status输出实际上最快捷的方式是直接用journalctl -xeu docker查看日志。Docker如果在启动过程中遇到权限问题、iptables问题、overlay2不支持问题都会在journal日志里留下非常明确的报错信息。4.5 配置开机自启动服务能够正常手动启动后设置开机自启systemctl enable docker这条命令会在systemd的多用户目标multi-user.target下创建docker服务的符号链接。以后机器重启后Docker会自动拉起。4.6 用hello-world镜像验证Docker功能很多教程会在这里让你执行docker run hello-world来验证但离线环境没有网络拉取镜像会失败。正确的做法是在联网机器上下载一个验证用的镜像导出成tar包再拷贝到目标机器导入。我通常验证用的是busybox因为它体积小、功能全# 在联网机器上执行 docker pull busybox:latest docker save busybox:latest -o busybox.tar然后把busybox.tar拷贝到目标服务器在目标服务器上导入docker load -i busybox.tar查看本地镜像列表docker images你会看到busybox镜像已经在列表里了。再跑一个容器验证功能docker run --rm busybox echo Docker works!如果输出Docker works!恭喜你的Docker离线安装已经大功告成。5. 常见问题与排查技巧实录5.1 启动失败Failed to connect to the Docker API这个问题我见得太多了尤其在刚装完Docker之后。报错信息通常是这样的Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?排查思路是先确认守护进程是否启动systemctl status docker ps aux | grep dockerd如果docker没在运行查看日志journalctl -xeu docker.service | tail -50日志里如果出现failed to start daemon: Error initializing network controller: error creating default bridge network说明iptables或者bridge模块出了问题。可以尝试systemctl restart docker还不行的话检查内核模块lsmod | grep br_netfilter modprobe br_netfilter有些精简系统默认没加载br_netfilter模块Docker的桥接网络就没法创建。加载后重建默认网络systemctl restart docker5.2 overlay2存储驱动不支持在旧内核或某些特殊文件系统上Docker可能无法使用overlay2报错会有exec: overlayfs或kernel does not support overlay fs字样。检查文件系统类型df -T /var/lib/docker如果发现是xfs并且开启了pquota特性支持没问题。但如果文件系统是ext3或者内核太老就得退而求其次改用vfs驱动。修改daemon.json中的storage-driver为vfs然后重启。虽然vfs性能差、占用磁盘多但至少是能用的方案。更好的根治办法是在离线环境下安装新版本内核包然后boot到新内核。但这会引入更多离线包依赖如果生产环境不允许重启机器那还是老实退回vfs方案。5.3 iptables相关问题Docker启动成功但容器无法访问外网或者端口映射不起作用十有八九是iptables规则问题。Docker启动时会向iptables写入大量自定义链比如DOCKER、DOCKER-USER。如果系统里存在其他防火墙软件比如firewalld、ufw且它们的规则和Docker冲突就可能导致网络异常。最简单的处理办法是停止并禁用firewalldsystemctl stop firewalld systemctl disable firewalld然后重启Docker让iptables规则重新初始化。注意有些公司有安全审计要求必须保留防火墙这时候你需要手动添加iptables规则放行Docker相关端口不要直接停防火墙。5.4 与旧版本Docker冲突如果你之前装过Docker的老版本比如docker-io、docker-engine再离线安装新版本时可能会冲突。解决方法是先彻底卸载旧版本yum remove docker docker-client docker-common docker-engine注意卸载Docker不会删除/var/lib/docker目录里的镜像和容器数据。如果你要保留这些数据卸载前先备份如果想彻底清理手动删除rm -rf /var/lib/docker5.5 常见问题速查表问题现象可能原因快速排查docker命令找不到docker-ce-cli未安装rpm -qa | grep docker守护进程无法启动kernel版本旧/依赖库缺失dockerd --debug查看详细输出overlay2 not supported内核模块未加载modprobe overlay容器无网络iptables规则被清空iptables -t nat -L -n查看默认链磁盘被容器日志写满未配置日志轮转配置log-opts并定期清理6. 离线环境的扩展思考与经验延伸6.1 离线仓库搭建从安装Docker到给Docker送粮食安装好Docker只是第一步离线环境更大的痛点是镜像怎么来。没有网络docker pull根本拉不了镜像你必须在有网的机器上把所有需要的镜像准备好。这里有一个高效的工作流程用一个脚本批量拉取镜像批量导出为tar包拷贝到内网服务器批量load导入我自己的做法是维护一份镜像清单images.txt每行一个镜像名和标签然后用脚本自动处理while read img; do docker pull $img docker save $img -o $(echo $img | tr / _).tar done images.txt内网机器上导入for f in *.tar; do docker load -i $f done这套流程虽然没有Harbor那种中央仓库方便但胜在简单直接特别适合临时环境和小团队。如果后续镜像数量大、版本更新频繁建议在生产内网部署一个Harbor私服。有两种方式一种是直接在内网服务器上跑Harbor容器另一种是搭建Docker Registry比较瘦身版。离线部署Harbor的过程本身也有一套方法论以后可以单独写一篇。6.2 多节点复制部署几分钟拉起一批Docker主机如果你需要在一批同配置的机器上批量安装Docker不需要每台都手动执行一遍安装命令。安装完第一台验证成功后把以下关键路径打包/usr/bin/docker*/usr/bin/containerd*/usr/bin/runc/usr/bin/ctr/etc/docker/拷到其他机器对应位置再执行systemctl enable --now docker就能快速拉起相同环境。这个方法本质上是把rpm安装后的文件直接拷贝分发虽然不够规范但在批量部署场景下效率极高。更好的方式是用Ansible写一个playbook把rpm离线包放到一个base目录然后在所有主机上执行rpm -ivh /path/*.rpm配合systemd的service文件管理。一套配置管几百台机器完全没问题。6.3 内网环境的镜像管理策略离线环境使用久了本地镜像会越积越多。我建议建立以下策略按项目命名镜像前缀使用项目代号后面跟服务名例如web-core/nginx:1.25.3维护一个镜像导出归档目录按日期分目录存放防止版本混乱定期清理悬空镜像执行docker image prune释放磁盘空间另外容器数据卷的备份和恢复也很重要。Docker的数据卷默认挂在/var/lib/docker/volumes/下备份时可以直接打包这个目录也可以使用docker run --volumes-from配合tar命令做在线热备。在离线环境里没有云磁盘快照可依赖这种原始的备份方式反而最可靠。6.4 国产化平台上的注意事项近几年国产化替代需求越来越大我遇到过不少在麒麟、统信UOS、龙芯、飞腾这些平台上装Docker的情况。这些平台的特点是基础系统可能基于CentOS或Debian的衍生版本但CPU架构可能不是x86_64。不同架构的Docker包必须从对应渠道获取。可以参考x86_64Docker官方仓库即可aarch64飞腾、鲲鹏、部分海光Docker官方也提供arm64版本包mips64el龙芯需要去龙芯开源社区或者第三方适配仓库找Docker官方不直接提供在国产化平台上系统默认的软件源里往往已经收录了docker包只是版本可能偏旧。如果你没有特殊版本需求直接用系统源里的版本最省事。如果非要新版就需要自己在有网的同架构机器上编译或者找对应适配包。6.5 离线环境下的Docker版本选择建议结合我自己的使用经验不同场景下Docker版本选择有讲究生产环境求稳定推荐Docker 20.10.x系列。这个版本成熟度高Bug反馈少兼容性覆盖广。如果要用Docker Compose V2和BuildKit的特性推荐24.0.x或25.0.x。如果你计划在Docker之上部署Kubernetes要注意集群组件对Docker版本的官方支持矩阵建议先查清楚再选版本。尽量避免使用过于新的版本在生产环境因为新版本刚发布时可能有一些regression问题离线环境修起来非常麻烦你需要重新准备一轮包。6.6 容器网络规划离线环境不要忽略的细节很多人在离线环境中装好Docker后就直接开跑容器网络配置完全沿用默认的bridge模式。这在单机场景下问题不大但如果你要在一台机器上跑多个业务容器容器间通信、端口映射规划做不好后面会非常痛苦。离线环境通常没有云平台提供的负载均衡和SDN功能所有网络联动都要靠Docker自己搞定。我在实际项目里的建议是明确端口规划表每个容器对外暴露的端口要提前登记避免冲突。优先使用自定义bridge网络而非默认bridge因为自定义网络提供内嵌DNS解析容器之间可以通过服务名互相访问docker network create --driver bridge --subnet172.20.0.0/16 my-net docker run --net my-net --name app -d myimage docker run --net my-net --name db -d mysqlapp容器里直接ping db就能通不用写死IP。容器与宿主机之间的端口映射尽量选择高位端口比如8080以上避免和系统服务端口撞车。如果多个环境共用一台宿主机比如测试环境可以用不同的自定义网络隔离不相干业务减少广播和误访问。6.7 systemd资源限制容器逃逸防护从配置做起离线环境的机器可能直接暴露在内网安全需求不比公网低。Docker的守护进程默认配置比较开放在离线环境里我强烈建议对容器做资源限制和保护配置。在daemon.json中补充{ icc: false, iptables: true, log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, default-ulimits: { nofile: { Name: nofile, Hard: 65536, Soft: 65536 } } }icc: false代表禁止容器间默认互相通信所有跨容器访问必须显式配置这能极大减小容器被入侵后的横向扩散风险。default-ulimits是限制单个容器能打开的文件描述符数量防止运行异常容器把宿主机文件句柄耗尽。开启容器能力限制也是重要一环。运行特权容器时使用--cap-dropALL --cap-addNET_BIND_SERVICE这样的白名单方式而不是直接--privileged放开全部权限。离线环境的镜像往往更新不及时漏洞可能比公网更难以快速修复保守的操作习惯能少惹很多麻烦。6.8 日志与监控离线环境容易漏掉的基础设施在公网环境我们可以用各种云监控服务看Docker状态但离线环境全得靠自己。Docker服务本身的状态监控建议用systemd的定时任务配合脚本检查d进程是否存活systemctl is-active docker || systemctl restart docker定时执行放到crontab里每分钟检查一次。容器级别的资源监控可以用docker stats手动看也可以写一个采集脚本把CPU和内存数据追加到本地文件后续用Grafana等工具展示。如果你的离线环境允许装cAdvisor那是最好的。cAdvisor本身也是一个容器离线导入运行即可。不过要注意cAdvisor版本和内核版本的兼容性有些版本在特定内核上会无法采集网络流量数据。7. 写在最后的实操体会7.1 离线安装看似简单实则颗粒度决定成败回头来看离线安装Docker的过程本身并不复杂一句话就是把包带进去装好配好启动。但真正让这件事变得有挑战的是对环境细节的判断和预案。拿我自己举例有一次在客户机房部署对方机器网卡上没有启用bridge-nf-call-iptables内核参数导致容器网络在跨节点访问时丢包严重排查了一整天。这样的问题你在文档里很难一眼看到必须靠内核参数检查和经验积累。所以我的建议是在动手离线安装之前把环境检查清单过一遍系统版本、架构、内核、文件系统、基础依赖、内核模块、防火墙状态。每一步都有对应的命令花十分钟检查完后面安装基本不会出幺蛾子。7.2 离线环境的后续维护比安装更重要装好只是起点。离线环境最大的敌人是版本漂移和依赖缺失。今天装的Docker 20.10一个月后可能在另一个项目里你需要24.0的新功能这时候你得重新准备一套离线包。维护一个离线包版本台账非常有必要我自己的习惯是在每台机器的/opt/docker-offline目录下放一个README.md记录这个离线包对应哪个版本、包含哪些依赖、是从哪台机器下载的、安装日期是什么。三个月后再回来维护你就不会一脸懵。7.3 一个小技巧用脚本固化整个安装过程如果你担心自己下次再装的时候会漏步骤可以准备一个安装脚本。把前面所有命令放到一个shell脚本里参数化安装包路径和版本号。脚本的核心逻辑就是解压、rpm安装、写配置、启动、启用自启。这样即便换了环境只要包齐全一条命令就能完成能省下大量重复劳动。我已经把脚本模板用在了多个项目里效果很好。希望这篇分享对你有实际帮助。如果你在离线安装过程中遇到的问题不在我列的场景里先看日志然后对照一下环境检查清单大概率能定位到问题。Docker离线安装这条路走通一次后面所有离线环境下的容器化部署都会顺很多。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →