ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Docker 24.0.5 离线安装实战:内网 CentOS 7.9 部署与避坑指南

Docker 24.0.5 离线安装实战:内网 CentOS 7.9 部署与避坑指南

简介:这份资源面向需要在无外网或内网环境中部署容器服务的运维与开发人员,提供 Docker 24.0.5 的完整离线安装方案,解决服务器无法联网拉取依赖、安装过程反复报错的痛点。压缩包共 18 个文件,以 17 个 rpm 依赖包和 1 个 sh 安装脚本为主,整体约 108.02MB,涵盖 docker-ce、docker-ce-cli、containerd.io、docker-buildx-plugin、docker-compose-plugin 等核心组件,以及 container-selinux、fuse-overlayfs、slirp4netns、libcgroup 等运行依赖,并附带 docker compose 命令支持。执行 install_docker.sh 即可完成部署,脚本需运行两遍,安装后 Docker 会自动启动。目前已有 935 人学习下载,适合需要快速搭建离线容器环境、减少依赖排查时间的读者参考使用。

1. 内网服务器上跑容器:为什么我死磕 docker 24.0.5 离线安装

上周帮一个做工业视觉的团队处理产线边缘节点,机器全是内网 CentOS 7.9,连不了外网,但算法同事扔过来一个 docker 镜像包,说“你装个 docker 跑一下就行”。听起来简单,实际动手才发现:yum 源不通、docker 官方脚本拉不下来、连 containerd 的依赖都得手动凑。这就是 docker 离线安装的典型场景——不是炫技,是没网逼出来的。

docker 24.0.5 这个版本在离线环境里算是个分水岭:它把 containerd 和 runc 的依赖关系理得比较清楚,二进制包拆得也干净,不像早期版本那样动不动就缺 libseccomp 或者 iptables 版本对不上。如果你手头也是内网机器、安全加固过的系统、或者边缘设备,这篇就是把我踩过的坑和能直接抄的步骤摊开讲。新手能照着走完,熟手可以重点看参数和排错那几段。

2. 离线包怎么选:二进制包、rpm 包和静态包的取舍

2.1 三种离线安装方式的真实差异

docker 离线安装常见三条路:二进制 tar 包、rpm/deb 包、以及静态编译包。我一般优先选二进制 tar 包,原因是它不依赖系统包管理器,解压就能用,升级也简单——把旧二进制换掉、重启服务就行。rpm 包适合有内部 yum 仓库的团队,能走yum localinstall统一管理,但依赖链一断就卡住,尤其是 selinux 和 libc 版本。静态包体积大,但胜在“扔进去就能跑”,适合系统库版本特别老的机器。

docker 24.0.5 的二进制包官方拆成四个核心组件:dockerd、dockerCLI、containerd、runc。离线包里通常还会带docker-proxy和docker-init。别小看后面这两个,容器端口映射和--init参数就靠它们,缺了会报一些莫名其妙的错。

2.2 版本对齐:别让 containerd 和 runc 拖后腿

docker 24.0.5 配套的 containerd 建议用 1.6.x 系列,runc 用 1.1.x。我见过有人只换了 dockerd 二进制,containerd 还是老版本,结果docker run直接卡在starting container process。原因是 24.x 对 OCI runtime 的调用协议有调整,版本错位就会在runc create阶段翻车。

检查版本用这几条命令,装完必须跑一遍:

# 查看 docker 服务端和客户端版本 docker version # 单独看 containerd 版本 containerd --version # 看 runc 版本 runc --version

逻辑说明:docker version会分别输出 Client 和 Server 两段,Server 段里的 Engine 版本必须是 24.0.5。containerd --version确认是 1.6.x,runc --version确认 1.1.x。三个都对上,后面才稳。

2.3 离线包目录结构长什么样

拿到手的离线包一般是个 tar.gz,解压后目录大概是这样:

路径内容用途
/usr/bin/dockerddocker 守护进程核心服务
/usr/bin/dockerCLI 客户端敲命令用
/usr/bin/containerd容器运行时管理容器生命周期
/usr/bin/runcOCI 运行时真正起进程
/usr/bin/docker-proxy端口代理-p 映射依赖
/usr/bin/docker-initinit 进程--init 参数依赖
/etc/docker/配置目录daemon.json 放这
/usr/lib/systemd/system/docker.servicesystemd 单元开机自启

我一般会先tar -tzf看一眼包内清单,确认这几个文件都在,再往系统里放。缺docker-proxy的话,-p 8080:80这种映射会直接失败,报failed to start proxy。

3. 手把手落地:从解压到 systemd 托管的完整命令

3.1 停旧服务、清残留

如果机器上装过 docker,先停干净。别直接覆盖,残留的 socket 文件和 iptables 规则会干扰新版本。

# 停止可能存在的旧 docker 服务 systemctl stop docker 2>/dev/null systemctl stop containerd 2>/dev/null # 删掉旧的 socket 和运行时目录 rm -rf /var/run/docker.sock rm -rf /var/run/docker rm -rf /var/lib/docker # 清理可能残留的 iptables 规则(谨慎,确认没有其他服务依赖) iptables -t nat -F DOCKER 2>/dev/null iptables -t filter -F DOCKER 2>/dev/null

逻辑说明:/var/lib/docker是镜像和容器数据的存放地,如果是从旧版本升级且想保留数据,这一步别删。但如果是全新安装或者数据不重要,删掉能避免元数据版本不兼容。iptables 那两条只在确认没有其他容器在跑的时候执行,否则会断掉已有容器的网络。

3.2 解压二进制并放到系统路径

# 解压离线包 tar -xzf docker-24.0.5-offline.tar.gz -C /tmp/docker-offline # 把二进制复制到 /usr/bin cp /tmp/docker-offline/dockerd /usr/bin/ cp /tmp/docker-offline/docker /usr/bin/ cp /tmp/docker-offline/containerd /usr/bin/ cp /tmp/docker-offline/containerd-shim-runc-v2 /usr/bin/ cp /tmp/docker-offline/runc /usr/bin/ cp /tmp/docker-offline/docker-proxy /usr/bin/ cp /tmp/docker-offline/docker-init /usr/bin/ # 给执行权限 chmod +x /usr/bin/dockerd /usr/bin/docker /usr/bin/containerd \ /usr/bin/containerd-shim-runc-v2 /usr/bin/runc \ /usr/bin/docker-proxy /usr/bin/docker-init

逻辑说明:containerd-shim-runc-v2这个文件容易被忽略,它是 containerd 和 runc 之间的垫片,缺了容器起不来。chmod +x必须做,有些离线包解压后权限是 644,直接跑会报Permission denied。

3.3 配置 daemon.json 和 systemd 单元

/etc/docker/daemon.json是 docker 的核心配置,离线环境里我一般会改这几项:

{ "data-root": "/var/lib/docker", "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" }, "storage-driver": "overlay2", "iptables": true, "live-restore": true }

参数说明:native.cgroupdriver=systemd在 CentOS 7 上必须加,否则 kubelet 对接时会报 cgroup 驱动不一致。storage-driver选 overlay2,前提是内核 4.x 以上且文件系统支持,overlay在老内核上才用。live-restore让 docker 守护进程重启时容器不停,产线环境很实用。log-opts限制日志大小,不然跑几个月磁盘就满了。

systemd 单元文件/usr/lib/systemd/system/docker.service内容:

[Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target firewalld.service Wants=network-online.target [Service] Type=notify ExecStart=/usr/bin/dockerd ExecReload=/bin/kill -s HUP $MAINPID LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity TimeoutStartSec=0 Delegate=yes KillMode=process Restart=on-failure StartLimitBurst=3 StartLimitInterval=60s [Install] WantedBy=multi-user.target

逻辑说明:Type=notify让 systemd 等 dockerd 发就绪信号,比simple更可靠。LimitNOFILE=infinity避免容器多的时候文件描述符不够。Delegate=yes允许容器内管理自己的 cgroup。这些参数在离线环境里尤其重要,因为出问题没法上网搜。

3.4 启动并验证

# 重载 systemd 配置 systemctl daemon-reload # 启动 docker systemctl start docker # 设置开机自启 systemctl enable docker # 验证 docker info docker run --rm hello-world

逻辑说明:docker info会输出存储驱动、cgroup 驱动、运行时版本等关键信息,重点看Storage Driver: overlay2和Cgroup Driver: systemd。hello-world镜像如果离线包里没带,需要提前docker load进去。离线环境跑docker run之前,确认镜像已经导入,否则会报Unable to find image locally。

4. 避坑排查:离线安装最容易翻车的五个点

4.1 现象:dockerd 启动报 “failed to start daemon: error initializing graphdriver”

原因:/var/lib/docker目录下有旧版本残留的存储驱动数据,overlay2 初始化时读到不兼容的元数据。

解决:停掉 docker,备份后清空/var/lib/docker,重新启动。如果数据重要,先用旧版本 docker 把镜像docker save出来,再清空目录、装新版本、docker load回去。

4.2 现象:容器能起但网络不通,docker run -p映射无效

原因:docker-proxy二进制没放对位置,或者 iptables 的FORWARD链被系统安全策略默认 DROP。

解决:确认/usr/bin/docker-proxy存在且有执行权限。然后检查iptables -L FORWARD,如果默认策略是 DROP,加一条iptables -A FORWARD -i docker0 -j ACCEPT。有些加固脚本会把 docker0 网桥也禁掉,用ip link show docker0确认网桥存在。

4.3 现象:docker version客户端能显示,Server 段报 “Cannot connect to the Docker daemon”

原因:dockerd 没起来,或者 socket 文件路径不对。离线安装时如果手动改过># 导出镜像,指定输出文件 docker save -o /tmp/nginx-1.25.tar nginx:1.25 # 压缩一下,传输更快 gzip /tmp/nginx-1.25.tar # 传到内网机器后解压导入 gunzip /tmp/nginx-1.25.tar.gz docker load -i /tmp/nginx-1.25.tar

逻辑说明:-o指定输出文件比重定向更稳,避免终端编码问题。gzip能压掉 30% 到 50% 的体积,尤其是镜像里有大量文本层的时候。导入后docker images确认镜像 tag 和 ID 都在。

5.2 版本回退:怎么从 24.0.5 退回旧版本

有时候新版本和现有编排工具不兼容,需要回退。步骤和安装反过来:

# 停服务 systemctl stop docker # 备份当前二进制 mkdir -p /opt/docker-backup/24.0.5 cp /usr/bin/dockerd /usr/bin/docker /usr/bin/containerd \ /usr/bin/runc /usr/bin/docker-proxy /usr/bin/docker-init \ /opt/docker-backup/24.0.5/ # 替换成旧版本二进制 cp /tmp/docker-old/dockerd /usr/bin/ cp /tmp/docker-old/docker /usr/bin/ # ... 其他组件同理 # 重启 systemctl start docker docker version

逻辑说明:回退前一定要备份当前二进制,不然想再升回来又得重新找包。/var/lib/docker的数据一般跨版本兼容,但如果旧版本不支持 overlay2 的某些特性,可能需要临时切到vfs驱动把数据导出来再切回去。

5.3 验证清单:装完必须过的五道关

我每次离线装完 docker,都会按这个清单跑一遍,少一道都不放心:

检查项命令预期结果
版本对齐docker versionServer 24.0.5,containerd 1.6.x
存储驱动docker info | grep Storageoverlay2
cgroup 驱动docker info | grep Cgroupsystemd
网络映射docker run -d -p 8080:80 nginx宿主机 curl localhost:8080 有响应
开机自启systemctl is-enabled dockerenabled

这五道关过了,基本就能交付了。最后说个血泪经验:离线环境里千万别随手docker system prune -a,没有外网重新拉镜像,删了就真没了。从那以后我每次装完 docker,第一件事就是把常用基础镜像docker save一份放到备份目录,再配个定时任务每周导一次。希望帮到你。

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进