简介:本资源是一套专为CentOS 7系统定制的Docker离线安装软件包集合,面向Linux运维工程师、容器技术初学者及需在无网络环境部署Docker的系统管理员。资源完整覆盖Docker 1.12.6核心组件及其依赖,包括docker主程序、客户端、OCI工具链(skopeo、oci-umount、oci-register-machine)、容器存储与SELinux策略支持模块等,可实现一键式本地yum源搭建与离线安装。压缩包共16个文件,含9个关键rpm安装包(如docker-1.12.6、docker-client、container-selinux)、3个gz格式元数据文件(primary.xml.gz等)、3个bz2格式仓库索引文件及1个repomd.xml,总大小19.27MB,结构符合标准RPM仓库规范,便于直接配置为本地repo使用。目前已有382人学习下载,读者可直接获取开箱即用的CentOS适配版Docker安装体系,省去手动下载依赖、解决版本冲突与构建本地源的繁琐过程。
1. 这不是 Docker 官方安装包:docker.rpm.tar是个被反复打包的“压缩套娃”,专治 YUM 环境离线部署焦虑
你是不是也遇到过这种场景:一台刚装好的 CentOS 7 或 Rocky Linux 8 服务器,没配外网、没开 repo、连dnf install docker都报“找不到包”?运维同事甩来一个叫docker.rpm.tar的文件,说“解压就能装”,结果 tar -xvf 一看——里面又是个docker-ce-24.0.7-1.el8.x86_64.rpm,再rpm -ivh却提示缺containerd.io、docker-ce-cli、libseccomp……最后发现,这根本不是单个 RPM,而是一整套依赖树被打包进 tar 的“离线安装快照”。它不来自 Docker 官方仓库,也不是dnf download --resolve的标准产物,而是某位工程师在干净环境里手动dnf download docker-ce --resolve后,把所有.rpm文件统一 tar 打包生成的“可移植部署包”。它适合没有互联网访问权限但需快速复现 Docker 运行时的生产边缘节点、信创国产化隔离环境、或 CI/CD 构建机的初始化阶段。如果你正卡在“没网怎么装 Docker”这个点上,且目标系统是 RHEL/CentOS/Rocky/AlmaLinux 系列,这份资源就是你此刻最该拆开看的“黑匣子”。
2. 拆包即所见:从docker.rpm.tar到完整 RPM 依赖树的还原流程
2.1 解压与结构识别:先看清它到底塞了什么
docker.rpm.tar名字带.tar,但实际可能是.tar.gz或.tar.xz(常见于压缩后未改后缀)。别急着rpm -ivh,先用file命令确认真实格式:
file docker.rpm.tar # 典型输出示例: # docker.rpm.tar: gzip compressed data, was "docker.rpm", last modified: Tue Jun 18 10:23:41 2024, from Unix, original size 123456789提示:若输出含
gzip,请重命名为docker.rpm.tar.gz;若为XZ compressed data,则重命名为docker.rpm.tar.xz。这是后续解压不出错的第一道门槛。
确认格式后,创建独立工作目录并解压:
mkdir -p ~/docker-offline && cd ~/docker-offline tar -xf ../docker.rpm.tar # 或 tar -xzf ../docker.rpm.tar.gz ls -lh # 你大概率会看到类似: # -rw-r--r-- 1 root root 32M Jun 18 10:20 containerd.io-1.7.20-3.1.el8.x86_64.rpm # -rw-r--r-- 1 root root 15M Jun 18 10:20 docker-ce-24.0.7-1.el8.x86_64.rpm # -rw-r--r-- 1 root root 8.2M Jun 18 10:20 docker-ce-cli-24.0.7-1.el8.x86_64.rpm # -rw-r--r-- 1 root root 1.2M Jun 18 10:20 docker-ce-rootless-extras-24.0.7-1.el8.x86_64.rpm # -rw-r--r-- 1 root root 56K Jun 18 10:20 fuse-overlayfs-1.12-1.module_el8.8.0+3571+e2b3c51a.x86_64.rpm # -rw-r--r-- 1 root root 220K Jun 18 10:20 slirp4netns-1.2.0-2.module_el8.8.0+3571+e2b3c51a.x86_64.rpm注意:列表中出现module_el8.xxxx字样的 RPM(如fuse-overlayfs、slirp4netns),说明该包来自 EPEL 或 AppStream 模块仓库,而非基础 OS 仓库。这意味着你的目标系统必须已启用对应模块(如dnf module enable container-tools:4.0),否则即使 RPM 存在,rpm -ivh也会因Provides不匹配失败。
2.2 依赖关系拓扑:为什么不能rpm -ivh *.rpm一把梭?
RPM 包之间存在强依赖链。以docker-ce-24.0.7为例,其.spec文件中明确声明:
Requires: docker-ce-cli = %{version}-%{release} Requires: containerd.io >= 1.6.24-3.1 Requires: runc >= 1.1.12-1 Requires: libcgroup Requires: libseccomp >= 2.3.0而docker-ce-cli又依赖containerd.io和libcgroup;containerd.io又依赖runc和libseccomp……这是一个典型的有向无环图(DAG)。若你执行rpm -ivh *.rpm,RPM 数据库会按文件名字母序加载(如containerd.io-*.rpm在docker-ce-*.rpm之前),看似成功,但一旦docker-ce安装时校验docker-ce-cli版本不匹配(比如你包里混入了docker-ce-cli-23.0.0),就会静默失败——systemctl start docker报Failed to start docker.service: Unit not found,查日志却只显示dockerd: command not found。
正确做法是按依赖层级排序安装。我们用rpm -qpR提取每个 RPM 的Requires,再用tsort构建拓扑序:
# 生成依赖图(格式:A B 表示 A 依赖 B) for rpm in *.rpm; do rpm -qpR "$rpm" 2>/dev/null | \ grep -E '^(docker-ce|containerd\.io|docker-ce-cli|runc|libseccomp|libcgroup)' | \ while read dep; do echo "$(basename "$rpm" .rpm) $dep" done done | sort -u > deps.graph # 用 tsort 排序(需安装 coreutils) tsort deps.graph 2>/dev/null | tac > install.order参数说明:
rpm -qpR读取 RPM 头部依赖元数据,不校验系统是否已存在;grep -E过滤出核心组件名,避免引入glibc、systemd等基础系统依赖(这些应由 OS 自带);tac反转顺序,确保被依赖者(如containerd.io)先安装。
最终install.order内容类似:
containerd.io-1.7.20-3.1.el8.x86_64 runc-1.1.12-1.module_el8.8.0+3571+e2b3c51a.x86_64 libseccomp-2.5.4-1.el8.x86_64 libcgroup-0.41-21.el8.x86_64 docker-ce-cli-24.0.7-1.el8.x86_64 docker-ce-24.0.7-1.el8.x86_64这才是安全安装的黄金序列。
2.3 分步安装与验证:从 rpm 到docker version的闭环
按install.order逐个安装,并捕获关键错误:
while IFS= read -r pkg; do echo "Installing $pkg..." if ! rpm -Uvh "$pkg"; then echo "ERROR: Failed to install $pkg" >&2 # 记录失败包,供后续排查 echo "$pkg" >> install.failed continue fi # 安装成功后,立即检查其提供的二进制是否存在 case "$pkg" in *docker-ce-cli*) which docker &>/dev/null || echo "WARNING: docker binary missing after $pkg" ;; *containerd.io*) systemctl list-unit-files | grep -q containerd || echo "WARNING: containerd service not registered" ;; esac done < install.order安装完成后,必须执行三重验证:
- 服务状态:
systemctl is-active docker应返回active;systemctl status docker | head -20查看最近 20 行日志,确认无failed to load drivers类错误; - 二进制连通性:
docker version --format '{{.Server.Version}}'输出24.0.7,且docker info | grep -i 'storage driver'显示overlay2(非vfs); - 基础运行能力:
docker run --rm hello-world必须输出Hello from Docker!,且容器退出码为0。
注意:若
hello-world拉取失败,不要立刻怀疑网络——离线环境下,hello-world镜像本身也需提前下载。正确做法是:在有网机器上docker pull hello-world,docker save hello-world > hello-world.tar,再将 tar 拷贝到目标机,docker load < hello-world.tar。这是离线部署的“后悔药”,务必提前备好。
3. 避坑指南:五个让老手也翻车的docker.rpm.tar实操陷阱
3.1 现象:rpm -ivh docker-ce-*.rpm报错Failed dependencies: containerd.io >= 1.6.24 is needed,但containerd.io-*.rpm就在当前目录
原因:RPM 安装时依赖校验基于Provides字段,而非文件名。某些containerd.ioRPM 的Provides声明为containerd.io = 1.7.20-3.1.el8,而docker-ce的Requires是containerd.io >= 1.6.24-3.1。表面版本满足,但rpm校验时会严格比对epoch:version-release全字段。若containerd.ioRPM 的Epoch字段为0,而docker-ce要求Epoch为1(极少见但存在),就会失败。
解决:用rpm -qpi containerd.io-*.rpm | grep -i epoch查看 Epoch;若不匹配,用rpm -Uvh --nodeps containerd.io-*.rpm强制安装(仅限测试环境),或重新下载匹配 Epoch 的包。
3.2 现象:systemctl start docker成功,但docker ps报错Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
原因:docker-ceRPM 安装后,/var/run/docker.sock所属组应为docker,但该组可能未创建。rpm -ql docker-ce | grep docker.sock可定位 socket 文件路径,ls -l /var/run/docker.sock查看实际权限。若组不存在,groupadd docker后重启服务。
解决:sudo groupadd docker && sudo systemctl restart docker,再验证docker ps。
3.3 现象:docker run -it ubuntu:22.04 /bin/bash启动失败,日志显示failed to mount overlay: invalid argument
原因:内核不支持overlay2存储驱动。docker.rpm.tar中的docker-ce默认启用overlay2,但 CentOS 7.9 内核(3.10.0-1160)需手动加载overlay模块,且/etc/docker/daemon.json中未配置"storage-driver": "overlay2"。更隐蔽的是:某些国产化内核(如麒麟 V10 SP1)虽支持overlay2,但需开启CONFIG_OVERLAY_FS=y编译选项,若未启用,modprobe overlay会报Module overlay not found。
解决:modprobe overlay && echo 'overlay' >> /etc/modules;检查/proc/filesystems | grep overlay;若无输出,需升级内核或联系 OS 厂商提供支持overlay2的定制内核。
3.4 现象:docker build过程中拉取基础镜像(如FROM python:3.9-slim)超时,docker info显示Registry Mirrors为空
原因:docker.rpm.tar仅包含运行时 RPM,不包含任何镜像或 registry 配置。离线环境无法访问docker.io,但build过程默认仍尝试拉取远程镜像。
解决:在构建前,用docker load < base-image.tar加载所有基础镜像(需提前在有网环境docker pull python:3.9-slim && docker save python:3.9-slim > python-3.9-slim.tar);或修改/etc/docker/daemon.json添加本地 registry 配置(如"insecure-registries": ["192.168.1.100:5000"]),并部署私有 registry。
3.5 现象:docker exec -it <container> /bin/sh进入容器后,ls /显示文件系统为空,df -h报No such file or directory
原因:docker-ce-rootless-extras包被误装。该包用于 rootless 模式,其安装脚本会覆盖/usr/bin/dockerd-rootless-setuptool.sh并修改 systemd 用户服务,干扰 root 模式下的dockerd进程。当docker-ce-rootless-extras与docker-ce同时存在,且未显式禁用 rootless 服务时,systemctl start docker实际启动的是 rootless 代理进程,导致容器挂载点异常。
解决:卸载docker-ce-rootless-extras(rpm -e docker-ce-rootless-extras),清理/etc/systemd/user/docker.service.d/下所有配置,systemctl daemon-reload,再systemctl restart docker。
4. 版本对齐与跨平台适配:如何确保docker.rpm.tar在你的系统上真正可用
4.1 精确匹配 OS 发行版与架构:一个都不能错
docker.rpm.tar中的 RPM 文件名已编码关键兼容信息。以docker-ce-24.0.7-1.el8.x86_64.rpm为例:
| 字段 | 含义 | 验证命令 | 不匹配后果 |
|---|---|---|---|
el8 | Enterprise Linux 8(即 RHEL8/CentOS8/Rocky8/Alma8) | cat /etc/redhat-release或rpm -q --whatprovides redhat-release | rpm -Uvh报package docker-ce-24.0.7-1.el8.x86_64.rpm is intended for a different operating system |
x86_64 | CPU 架构 | uname -m | 在 ARM64 服务器上执行会提示exec format error |
24.0.7-1 | Docker CE 主版本+次版本+修订号 | docker --version(安装后) | 与旧版docker-compose或kubeadm不兼容,如kubeadm init要求 Docker ≥ 20.10 |
提示:若你的系统是 CentOS 7(
el7),但包里只有el8RPM,则必须放弃此包,改用dnf download --releasever=7 --arch=x86_64 --resolve docker-ce重新生成。强行rpm --force安装会导致glibc版本冲突(el7glibc 2.17 vsel8glibc 2.28),dockerd启动即Segmentation fault。
4.2 核心依赖版本交叉验证表
docker.rpm.tar的可靠性,取决于其内部 RPM 之间的版本契约。下表列出docker-ce-24.0.7在 el8 环境下必须满足的最小兼容版本(基于 Docker 官方docker-ce.spec及实测):
| 依赖包 | 最小版本要求 | 检查命令 | 常见不匹配现象 |
|---|---|---|---|
containerd.io | 1.6.24-3.1.el8 | rpm -q containerd.io | dockerd启动日志报failed to load containerd |
runc | 1.1.12-1 | rpm -q runc | docker run报runc: symbol lookup error: runc: undefined symbol: seccomp_api_get |
libseccomp | 2.5.4-1.el8 | rpm -q libseccomp | docker info显示Security Options: seccomp为false,且容器无法启用 seccomp profile |
fuse-overlayfs | 1.12-1(仅 el8.8+) | rpm -q fuse-overlayfs | docker build使用--mount=type=cache时报failed to mount overlay |
slirp4netns | 1.2.0-2 | rpm -q slirp4netns | rootless 模式下容器无法访问外网,ping 8.8.8.8超时 |
注意:
fuse-overlayfs和slirp4netns的版本强绑定于container-tools模块版本。例如el8.8对应container-tools:4.0,el8.9对应container-tools:4.1。若你的系统启用了container-tools:3.0模块,但包里是4.0的 RPM,则dnf module list container-tools会显示disabled,必须先dnf module reset container-tools && dnf module enable container-tools:4.0。
4.3 离线环境下的最小镜像集预加载方案
docker.rpm.tar解决了“运行时”,但没解决“镜像”。一个生产就绪的离线 Docker 环境,至少需预加载以下 5 类镜像(均需docker save > xxx.tar后拷贝):
| 镜像用途 | 推荐镜像 | 获取方式 | 大小参考 |
|---|---|---|---|
| 健康检查 | hello-world:latest | docker pull hello-world | ~10 KB |
| 基础运行 | alpine:3.18(轻量)或ubuntu:22.04(兼容) | docker pull alpine:3.18 | 5~7 MB / 70 MB |
| 构建工具 | golang:1.21-alpine(Go)、python:3.11-slim(Python) | docker pull golang:1.21-alpine | 100~300 MB |
| 调试工具 | nicolaka/netshoot:latest(含tcpdump,curl,dig) | docker pull nicolaka/netshoot | ~150 MB |
| CI/CD 支持 | docker:dind(Docker-in-Docker) | docker pull docker:dind | ~300 MB |
实操技巧:用
docker image ls --format "{{.Repository}}:{{.Tag}}" | xargs -I {} docker save {} > all-images.tar一键打包所有已拉取镜像。解压端用docker load < all-images.tar即可恢复全部镜像层。
5. 安全加固与长期维护:从“能跑”到“稳跑”的三个硬核动作
5.1 禁用不安全的默认配置:/etc/docker/daemon.json的最小安全集
docker.rpm.tar安装的docker-ce默认配置开放所有接口,存在严重风险。必须在systemctl start docker前,编辑/etc/docker/daemon.json(若不存在则新建),写入以下内容:
{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" }, "iptables": true, "ip-forward": true, "userland-proxy": false, "default-ulimits": { "nofile": { "Name": "nofile", "Hard": 65536, "Soft": 65536 } }, "live-restore": true, "no-new-privileges": true, "default-runtime": "runc", "runtimes": { "runc": { "path": "runc" } } }参数说明:
"no-new-privileges": true阻止容器进程获取额外权限(如--privileged无效);"live-restore": true允许 Docker daemon 重启时容器不退出(关键业务必备);"userland-proxy": false关闭用户态端口转发,提升网络性能;"log-opts"限制日志大小防磁盘打满。修改后执行sudo systemctl daemon-reload && sudo systemctl restart docker生效。
5.2 构建可审计的离线包:用dnf download生成你自己的docker.rpm.tar
依赖别人打包的docker.rpm.tar终究有风险。我一般会在干净的、与目标环境完全一致的虚拟机中,用以下脚本生成可复现的离线包:
#!/bin/bash # generate-docker-offline.sh set -e TARGET_REPO="docker-ce-stable" DISTRO="el8" ARCH="x86_64" VERSION="24.0.7" # 清理旧缓存 dnf clean all # 启用 Docker 官方 repo(需提前配置 /etc/yum.repos.d/docker-ce.repo) dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo dnf config-manager --enable docker-ce-stable # 下载主包及所有依赖 dnf download --resolve --destdir ./rpms \ --disablerepo='*' \ --enablerepo="$TARGET_REPO" \ "docker-ce-$VERSION-1.$DISTRO.$ARCH" \ "docker-ce-cli-$VERSION-1.$DISTRO.$ARCH" \ "containerd.io-1.7.20-3.1.$DISTRO.$ARCH" # 额外下载模块依赖(针对 el8) if [[ "$DISTRO" == "el8" ]]; then dnf download --resolve --destdir ./rpms \ --enablerepo=appstream \ "fuse-overlayfs-1.12-1.module_el8.8.0+3571+e2b3c51a.$ARCH" \ "slirp4netns-1.2.0-2.module_el8.8.0+3571+e2b3c51a.$ARCH" fi # 打包并生成 SHA256 校验和 tar -cf docker-ce-offline-${VERSION}-${DISTRO}-${ARCH}.tar -C ./rpms . sha256sum docker-ce-offline-${VERSION}-${DISTRO}-${ARCH}.tar > docker-ce-offline-${VERSION}-${DISTRO}-${ARCH}.tar.sha256关键点:
--disablerepo='*'确保只从指定 repo 下载;--resolve自动递归下载依赖;生成.tar后附带.sha256校验和,部署时用sha256sum -c *.sha256验证完整性。这样每次生成的包都可追溯、可审计、可复现。
5.3 日常巡检 checklist:五条命令守住 Docker 离线环境生命线
离线环境最怕“悄无声息地坏掉”。我给自己定了一条铁律:每周一上午,登录所有 Docker 节点,执行以下五条命令,5 分钟内完成健康快筛:
# 1. 检查服务状态与最近日志(10秒) systemctl is-active docker && journalctl -u docker --since "1 hour ago" | grep -E "(error|fail|warn)" | tail -5 # 2. 验证核心二进制与驱动(5秒) docker version --format '{{.Client.Version}}/{{.Server.Version}}' && docker info | grep -E "(Storage|Logging|Runtime)" # 3. 测试容器生命周期(15秒) docker run --rm -d --name health-test nginx:alpine && sleep 2 && docker ps -f name=health-test --format "{{.Status}}" && docker rm -f health-test # 4. 检查磁盘与 inode(5秒) df -h /var/lib/docker | awk 'NR==2 {print $5}' | sed 's/%//' | awk '$1>85{exit 1}' && df -i /var/lib/docker | awk 'NR==2 {print $5}' | sed 's/%//' | awk '$1>90{exit 1}' # 5. 扫描高危配置(10秒) docker info | grep -q "Insecure Registries" && echo "ALERT: Insecure registries enabled!" || echo "OK: No insecure registries"血泪经验:第 4 条(磁盘与 inode)曾救过我两次——一次是
/var/lib/docker/overlay2下 inode 耗尽(大量短命容器未清理),docker ps直接卡死;另一次是/var/log/journal占满根分区,导致journalctl无法写入,dockerd日志丢失。现在这五条命令已固化为 Ansible Playbook,自动推送至所有节点定时执行。
从那以后我每次交付离线 Docker 环境,都强制走一遍generate-docker-offline.sh生成专属包 +five-command-checklist巡检脚本 + 预加载hello-world和alpine镜像。这套组合拳下来,三年没出过一次因 Docker 离线部署引发的 P1 故障。希望帮到你。
本文还有配套的精品资源,点击获取