☰
Docker离线安装全攻略:rpm本地源与静态二进制包实践
2026/10/10 3:21:55 网站建设 项目流程

简介:面向无外网或内网环境的运维与开发人员,这份离线安装包专门解决 Docker 24.0.5 在无法连接互联网时难以直接安装的问题,适合在 CentOS 7 等服务器上快速搭建容器运行环境。资源以 tar.gz 格式打包,共 18 个文件,其中 17 个是 RPM 依赖包、1 个是安装脚本,整体约 108.02 MB,便于拷贝到内网主机;依赖包覆盖 Docker 引擎、命令行客户端、containerd、buildx、Compose 插件等核心组件,也包含 rootless 扩展和常见系统依赖。离线部署时按包内说明执行脚本即可完成安装并自动启动服务,无需再逐一下载组件;从解压到使用基本一站式完成,可避免逐个寻找 rpm、处理依赖冲突的繁琐工作,也便于统一环境版本。已有 935 人学习这一资源,适合需要批量初始化服务器 Docker 环境、维护离线安装源或希望避免依赖缺失问题的团队使用。

1. 为什么偏偏是 24.0.5:离线安装的真实场景与版本选择

生产环境里最怕的不是没网,而是没网的时候还要装 Docker。给内网机柜、隔离区服务器装容器运行时,不能 apt-get 也不能 curl 脚本,唯一的办法是提前准备好东西搬进去。而 24.0.5 这个版本号在离线场景里出现频率特别高——它不是最新,却在稳定性和老内核兼容性之间取了一个非常舒服的位置,很多跑 CentOS 7 / 兼容内核的老机器点名要它。

这篇笔记就围绕“没有任何外网连接的目标机器”这个前提,拆解两条可行路线:基于 rpm 包搭建本地源,以及直接部署官方静态二进制包。你可以跟着命令复现,也可以在方案选型时直接拿走结论。适合的对象是运维、实施工程师和需要在客户内网交付容器环境的开发者,不涉及集群调度,只专注把单机 Docker 装到能用的程度。

2. 离线安装的两条路线:rpm 本地源与静态二进制包怎么选

2.1 先搞懂离线安装到底在解决什么

离线安装 Docker 的本质是“依赖管理”。在线环境下,yum 会替你解析 docker-ce 和它的运行库、容器运行时组件之间的依赖关系;离线之后,这套解析机制失效,你就得自己把依赖链条补齐。

Docker 24.0.5 的软件包并不是一个孤立的二进制,它至少牵扯到 CLI 工具、容器运行时 containerd、以及构建插件和网络插件。rpm 方式的好处是:只要把对应发行版的所有依赖 rpm 一次性拉齐,目标机器上 yum 就能按本地仓库完成安装,后续卸载、升级也完全走系统包管理流程,不留下散落文件。

静态二进制包方案则是另一套逻辑:官方把 dockerd、containerd、runc 等组件直接编译好打进一个 tar 包,解压后的二进制文件复制到系统路径即可运行。它不依赖发行版的包管理,更不关心 yum 源长什么样,适合那些系统版本不再被官方仓库覆盖的老机器。

两条路线的差别会在升级维护上放大:rpm 方案升级时只需要换本地源里的新包再执行 yum update;二进制方案升级则要重新下载整套 tar 包覆盖二进制文件,几乎没有增量升级的余地。下面用一个表把决策因素摆出来。

对比项rpm 本地源方案静态二进制包方案
对目标系统要求必须匹配发行版版本与架构只要求 glibc 与内核特性满足
依赖处理下载时一次性拉全,yum 自动解析无依赖,自带运行组件
安装耗时依赖仓库建好后约 1 分钟复制二进制加写配置约 3 分钟
升级方式替换本地源包后 yum update重新覆盖二进制文件
适合场景CentOS/RHEL 系内网批量交付特殊发行版、精简系统、应急恢复

2.2 网络隔离下的准备策略:一台有网过渡机是必备的

无论选哪条路线,你都需要一台能联网、且和目标机器同架构同发行版的“过渡机”。常见做法是:在有网机器上完成下载和打包,用 U 盘或内网共享目录把材料搬运进去。架构匹配是这里最容易翻车的点——x86_64 的包搬到 arm64 机器上,安装阶段不一定报错,但 dockerd 一启动就会直接非法指令崩溃。

我做这类交付一般会在过渡机上先把完整流程演一遍:装好、启动、跑容器,再把环境清理干净重新打包。这样做的好处是,你在过渡机上已经解决掉的坑,就不会再捎带给内网机器。

还有一个需要提前决策的事:要不要离线导入镜像。如果目标机器上的业务完全靠内网私有仓库拉镜像,那这一步可以跳过;如果私有仓库还没建,那 docker save 出来的镜像 tar 包必须和安装包一起打包送进去,否则 Docker 装好了也无事可做。

3. 路线一:用 rpm 包搭本地源,把 docker-ce 装到内网机器

3.1 在过渡机上拉取依赖包,yumdownloader 的正确用法

首先要保证过渡机装了 yum-utils 工具集。接下来在过渡机上建一个目录,把所有 docker-ce 相关包连同依赖一起下载到里面,命令如下:

mkdir -p /data/docker-rpms cd /data/docker-rpms # 只下载不安装,--resolve 会自动把依赖包一并拉下来 yumdownloader --resolve \ --destdir=/data/docker-rpms \ docker-ce docker-ce-cli containerd.io docker-compose-plugin

这一步的逻辑是:--destdir指定输出目录;--resolve让 yum 把依赖关系展开,比如 containerd.io 依赖的 libseccomp 也会被下载进来。建议加上docker-compose-plugin,如果项目后面用到 compose 文件,可以省掉二次送包的麻烦。

注意看下载结束后的文件列表,单独执行下面这条命令确认:

ls -lh /data/docker-rpms/

文件数量通常在 10 到 20 个之间,取决于基础系统里已经安装了哪些依赖。如果只有孤零零的三五个包,说明--resolve没有生效,检查一下过渡机的 yum 源是否完整——尤其是 epel 源缺失时,libseccomp 这类依赖往往拉不下来。

3.2 用 createrepo 生成仓库元数据,yum 才能识别这个目录

拉到一堆 rpm 文件还不够,yum install 需要一个“仓库索引”。这个动作由 createrepo 完成,生成 repodata 目录后,把整个文件夹拷进内网机器即可。

# 安装 createrepo 工具(如果过渡机上没有) yum install -y createrepo # 为 rpm 目录生成仓库索引 createrepo /data/docker-rpms

生成完毕后,/data/docker-rpms/repodata/下会出现以 repomd.xml 结尾的文件,这就是 yum 识别仓库的依据。之后把这个目录原封不动复制到 U 盘,进入目标内网机器后放到/opt/docker-rpms,本地源就位。

3.3 内网机器配置本地 repo 文件并完成安装

在目标机器上新建仓库配置文件:

vi /etc/yum.repos.d/docker-offline.repo

写入以下内容:

[docker-offline] name=Docker Offline Repository baseurl=file:///opt/docker-rpms enabled=1 gpgcheck=0

baseurl指向本地目录路径,注意 file 协议的写法是file://加绝对路径。gpgcheck=0在这里是必要的——离线环境导入 GPG 公钥很繁琐,内网可信管道内关闭校验是常见操作。如果过不了安全审计,可以提前把公钥文件拷进机器,再改成gpgcheck=1加gpgkey=file:///path/RPM-GPG-KEY。

执行安装:

yum clean all yum makecache yum install -y docker-ce docker-ce-cli containerd.io

yum clean all是为了清掉系统里可能存在的旧缓存,makecache重新生成缓存,让 yum 识别到新的本地仓库。如果安装时报依赖冲突,大概率是系统里已经装了某个旧版本 docker 相关包,用yum remove清掉后再装。

3.4 启动前的必要检查:内核模块和 sysctl

装完先别急着systemctl start docker。离线机器往往是老内核,missing 内核模块会导致 Docker 起得来但容器跑不住。检查并加载核心模块:

modprobe overlay modprobe br_netfilter # 写入开机加载配置 cat > /etc/modules-load.d/containerd.conf <<EOF overlay br_netfilter EOF

然后是网络转发配置。不改这个,容器内外网不通,NAT 规则没生效:

cat > /etc/sysctl.d/99-docker.conf <<EOF net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 EOF sysctl --system

这两步是离线安装里最容易被跳过的。在线装 Docker,启动脚本经常顺手把模块和 sysctl 一起处理了;离线环境下别人很难替你兜底,只能在部署文档里显式写出来。全部配置完成后,启动并设置开机自启:

systemctl start docker systemctl enable docker systemctl status docker --no-pager

4. 路线二:静态二进制包 + systemd,让 dockerd 五分钟跑起来

4.1 解压部署二进制,理解官方包里的文件结构

静态二进制方案适合对包管理不敏感、或者发行版已经停止维护的老系统。在有网机器上拿到官方发布包,文件名类似 docker-24.0.5.tgz。先不要直接复制进系统,找个临时目录解压看包内结构:

mkdir -p /tmp/docker-install tar -xzf docker-24.0.5.tgz -C /tmp/docker-install ls -lh /tmp/docker-install/docker/

包内是 containers 相关二进制集合,包含 dockerd、containerd、containerd-shim-runc-v2、runc 等,还有一个 docker 客户端。把这些文件复制到系统路径:

cp /tmp/docker-install/docker/* /usr/local/bin/

/usr/local/bin比/usr/bin更适合手工部署,这个目录优先级本身就排在系统路径前面,而且升级时替换起来语义更清晰——你知道哪些文件是自己放进去的,哪天要卸载直接删目录即可。

4.2 手写 docker.service 和 docker.socket 单元文件

二进制部署没有 rpm 包来生成 systemd 单元,必须自己写。先创建 docker.service:

vi /etc/systemd/system/docker.service

写入单元配置:

[Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target firewalld.service containerd.service Wants=network-online.target Requires=docker.socket [Service] Type=notify ExecStart=/usr/local/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=0 RestartSec=2 Restart=always LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity TasksMax=infinity Delegate=yes KillMode=process [Install] WantedBy=multi-user.target

然后创建 docker.socket,它是这套配置里容易被忽略的一块。Docker 默认监听在 fd 3 上,由 socket 激活机制拉起:

vi /etc/systemd/system/docker.socket
[Unit] Description=Docker Socket for the API [Socket] ListenStream=/var/run/docker.sock SocketMode=0660 SocketUser=root SocketGroup=docker Accept=no [Install] WantedBy=sockets.target

Accept=no表示 socket 由 systemd 管理,连接到达时由 dockerd 自己 accept,这样能减少进程 fork。SocketGroup=docker配合 0660 的权限,让 docker 组里的用户可以直接用客户端,不必每次 sudo——这是很多人在二进制安装后抱怨“permission denied”的根源,其实是 socket 用户组没配。

4.3 daemon.json 离线配置:data-root 和数据目录规划

二进制部署模式下,dockerd 启动默认把数据放在/var/lib/docker。内网机器根分区容量经常很紧张,镜像 tar 包一多就会把根分区塞满。建议提前配置数据目录,顺便把日志驱动参数一起固化进配置:

mkdir -p /etc/docker vi /etc/docker/daemon.json

写入一个适合离线单机的精简配置:

{ "data-root": "/data/docker", "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "5" }, "storage-driver": "overlay2", "iptables": true }

>systemctl daemon-reload systemctl start docker.socket systemctl start docker.service systemctl enable docker.socket docker.service docker version --format '{{.Server.Version}}'

输出24.0.5即说明 dockerd 已经跑起来。进程异常的话,用journalctl -u docker.service -n 50 --no-pager看日志,这一步比瞎猜配置要有用得多。

5. 离线安装避坑清单:五个高频问题和对应排查方法

5.1 yum 安装时提示依赖缺失,本地源明明有包

现象:执行yum install docker-ce后,报错显示Requires: xxx.so.1()(64bit)一类的缺失依赖,但翻开/opt/docker-rpms目录看,相关 rpm 文件都在。

原因:rpm 目录不是仓库,yum 不扫描目录内容,只认 repodata 索引。createrepo 生成的索引里如果没包含缺失的依赖项,或者过渡机上--resolve漏拉,就会发生这种情况。

解决:回到过渡机重新执行yumdownloader --resolve,这次把报错里缺失的包名手动加进命令末尾。再把新的 rpm 复制进内网目录,重新执行createrepo --update /opt/docker-rpms/更新索引,最后yum clean all && yum makecache。注意日常运维时只用--update参数,不要重复全量生成索引。

5.2 静态二进制部署后 dockerd 启动即崩溃

现象:systemctl start docker后服务进入 failed 状态,journalctl里出现类似failed to start daemon: error initializing graphdriver的信息。

原因:最常见的原因是存储驱动不可用。老内核的 overlay 模块没加载,或者系统文件系统不支持 overlay2 的 d_type 特性,dockerd 初始化数据目录失败直接退出。

解决:先确认模块加载情况,lsmod | grep overlay没输出就手动modprobe overlay并写进/etc/modules-load.d/。如果模块本身缺失,把 daemon.json 里的存储驱动改成vfs,代价是镜像层文件会重复存储,但能先把 Docker 跑起来。注意 vfs 方案只在应急时用,镜像大了之后磁盘占用会非常难看。

5.3 镜像 load 成功但容器运行时网络不通

现象:docker load -i xxx.tar显示镜像已导入,docker run也成功创建了容器,但容器内ping外网不通,curl也没有任何响应。

原因:这一步往往是内核参数问题。离线机器默认没有打开 IPv4 转发,或者 iptables 的 bridge-nf-call 内核参数没开启,容器网络流量在 bridge 层就被丢弃了。

解决:沿用第三章的 sysctl 配置,net.ipv4.ip_forward和net.bridge.bridge-nf-call-iptables都设为 1,然后sysctl --system重载。如果内网机器没有bridge内核模块,那桥接和 iptables 联动就不可能生效,考虑用 host 网络模式先验证容器进程本身是否正常。

5.4 非 root 用户执行 docker 命令报权限不足

现象:普通用户运行docker ps报permission denied while trying to connect to the Docker daemon socket。

原因:客户端连接的是/var/run/docker.sock,这个 socket 文件的组权限没有放开给普通用户。rpm 安装时 docker 包会创建 docker 用户组,但静态二进制方案不会自动做这件事。

解决:手动补上后续步骤,把用户加进组:groupadd docker(如果还不存在)+usermod -aG docker 用户名,然后让用户重新登录会话。注意:usermod只对之后的登录生效,用户当前所在 shell 还是要先退出重进。

5.5 重启机器后 Docker 没有自动恢复

现象:内网机器断电重启,登录后docker ps提示Cannot connect to the Docker daemon,systemd 里 docker 服务却是 enable 状态。

原因:静态二进制方案里,docker.socket 和 docker.service 只是 enable 了,但 containerd 这个外部依赖并没有注册成 systemd 服务。dockerd 启动时如果 containerd 连接失败,会重试数次后放弃。

解决:不要手动去前台拉 containerd,直接把 containerd 也做成 systemd 单元,让 docker.service 声明依赖它。在/etc/systemd/system/containerd.service里写一个 ExecStart 指向/usr/local/bin/containerd的配置,然后在 docker.service 的[Unit]段加Requires=containerd.service和After=containerd.service。这样重启后 systemd 会按序拉起 containerd,再拉 dockerd。

6. 镜像离线迁移:批量 save/load 与冒烟验证的一条龙习惯

装好了 Docker 以后,真正的交付才完成一半。我一般会在目标机器上加两步:批量导出镜像和启动验证容器。在业务机器上跑一个批量导出脚本,把过渡机上的所有镜像打包成单文件:

mkdir -p /data/images cd /data/images # 遍历本地镜像,过滤掉中间层,每个镜像单独导出一个 tar 包 docker images --format '{{.Repository}}:{{.Tag}}' | grep -v '<none>' | while read img; do fname=$(echo "$img" | tr '/:' '__') docker save -o "${fname}.tar" "$img" done

tr '/:' '__'是为了把镜像名里的斜杠和冒号替换成下划线,避免嵌套目录问题。导出的文件拷贝到内网机器后统一执行docker load -i,逐个导入。这个过程中最容易犯的错是把 save 和 export 混着用——save 打包的是镜像分层结构,load 回去还能保留标签和历史;export 导出的是容器文件系统,import 回来是一个新镜像,标签会丢或者变成随机 IMAGE ID。离线交付务必用 save/load 这一对。

最后做一个冒烟验证。跑一个脱离网络也能启动的容器,确认 Docker 的完整生命周期没问题:

docker run -d --name smoke-test --rm alpine:3.19 sleep 300 docker exec smoke-test cat /etc/alpine-release

进程能起来、命令能执行,说明镜像加载正常、容器运行时工作正常。验证完直接docker rm -f smoke-test,把环境还给业务。我第一次做离线部署时就吃了 containerd 没注册成自启动服务的亏,机器掉电重启后 Docker 彻底失联,后来每次二进制部署都习惯把 containerd 和 docker 的单元文件一起写好,再也不会事后追着机房电话跑。这个习惯推荐你也保持住,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询