简介:docker19.03.9离线部署工具包面向内网、无外网环境下的容器运行环境搭建,适合运维工程师、系统管理员以及需要在隔离网络中快速交付Docker服务的技术团队。资源基于官方19.03.9稳定版本,将Docker引擎、systemd服务管理、环境配置文件与自动化安装脚本整合在一起,能有效规避手动逐台下载依赖、配置源和启动服务的重复劳动,显著提升批量部署效率。压缩包共含4个文件,主要包括.tgz程序包、.service系统服务文件、.sh安装脚本与.tpl配置模板,分别承担组件分发、服务托管、执行安装和运行参数生成等职责,结构紧凑、职责清晰,便于根据业务需要调整。整个资源包约57.69MB,可直接拷贝到离线主机中使用。目前已有9041人学习或下载,方案成熟度在实际场景中得到较多验证。通过这套离线工具,使用者可以拿到现成的Docker二进制、systemd配置、部署脚本和模板文件,了解从解压、注册服务、生成环境变量到启动容器的完整链路,尤其适合企业内部进行Docker版本固定、标准化交付和无人值守安装。
1. docker19.03.9 离线部署:把外网依赖提前锁死在安装包里
内网机器上装 Docker 19.03.9,最磨人的不是命令记不住,而是机器根本没有外网。yum 源不可用、依赖包缺一堆、镜像没地方拉,这三件事足以让半天排期变成一整周。所谓“docker19.03.9离线部署工具”,并不是某个开源软件的名字,而是一整套可复制的落地套路:一台有网机器把 RPM 依赖抓全、打成 tar,把业务镜像导出,把 daemon.json 和 systemd 配置写死,目标机解包后跑一个脚本就能完成装包、起服、导镜像。适合做内网交付、机房隔离环境、离线建设项目的运维工程师照着重现,少交点学费。
2. 离线安装包怎么凑:rpm 依赖树与版本锁定的取舍
2.1 为什么锁 19.03.9:生产环境验证过,编排模板都按它来
选 19.03.9 不是因为它最新,而是因为它是 2019-2020 年那波生产环境用得最稳的版本。当时 Kubernetes 1.18 的容器运行时兼容矩阵里,Docker 19.03 是主力推荐版本;大量业务镜像、docker-compose 模板、CI 流水线都是在这个版本上调试通过的。现在很多内网项目要求“指定版本部署”,手里拿到的材料往往就是 19.03.9 的包和配置,这也是它至今还在离线交付脚本里频繁出现的原因。
版本锁定还有一层现实考虑:离线环境升级成本极高。生产上跑着的容器编排和监控脚本,可能依赖某个版本的 Docker API 行为。19.03.9 之后 Docker 在 cgroup v2、非 root 运行等方向大步调整,内网机器内核和 systemd 版本未必跟得上。与其在生产环境赌新版兼容性,不如把验证过的 19.03.9 和配套的 containerd.io 锁死在安装包里,让所有目标机器长成一个样。
2.2 在有网机器上抓全依赖:yumdownloader 与 --resolve
离线包的核心工作,是在一台有外网、yum 源完整的机器上,把 docker-ce、docker-ce-cli、containerd.io 以及它们的所有依赖全部拉下来。常见做法是用 yumdownloader,它对 CentOS 7 这类老系统的依赖解析比手动一个个 rpm 靠谱得多:
# 先装 yum-utils,它提供 yumdownloader 命令 yum install -y yum-utils # 指定版本号下载,--resolve 会把依赖树一起拉下来 mkdir -p /root/docker19.03.9-pkgs yumdownloader --resolve --destdir=/root/docker19.03.9-pkgs \ docker-ce-19.03.9 \ docker-ce-cli-19.03.9 \ containerd.io这里的几个参数值得说清楚。--resolve是关键中的关键,它会分析这三个 rpm 的依赖关系,把 libseccomp、libltdl、policycoreutils-python 这类底层库一并下载,目标机装的时候才不会卡在“缺少依赖”上。--destdir指定输出目录,方便后面直接打包。docker-ce-19.03.9这种写法是让 yum 自己匹配对应的小版本,不需要去记完整的 release 号。
如果目标机需要配合 SELinux 策略使用,docker-ce 的依赖里还会出现 container-selinux 这类与安全策略相关的 rpm。抓完包后建议看一眼目录内容,确认 containerd.io 和 docker-ce-cli 都在里面。缺少 cli 包的症状很隐蔽:docker 命令找不到,但 dockerd 进程其实已经起来了,排查时会绕一大圈。
# 查看抓包结果,确认核心组件齐全 ls -lh /root/docker19.03.9-pkgs/ # 在目标机上模拟安装一遍,校验依赖是否齐全 rpm -ivh /root/docker19.03.9-pkgs/*.rpm --testrpm --test只是模拟安装,不写入系统。如果这一步报缺依赖,说明有网机器上抓包时漏了东西,回上一步补。这里我建议不要在目标机上用rpm --nodeps强装,虽然当时能装上,但运行时缺动态库会让容器起不来,而且报错信息跟真实原因离得很远。
2.3 目标机的安装顺序:能用 yum localinstall 就别碰 rpm --nodeps
把打包好的 rpm 目录整体拷到目标机后,安装顺序是一个值得较真的点。containerd.io 是最底层,docker-ce-cli 依赖它,docker-ce 依赖 cli,顺序反了必然报错。两个可用的方法:
# 方法一:yum localinstall 自动解析本地依赖 cd /root/docker19.03.9-pkgs yum localinstall -y ./*.rpm # 方法二:按依赖顺序手动 rpm -Uvh rpm -Uvh containerd.io-*.rpm rpm -Uvh docker-ce-cli-*.rpm rpm -Uvh docker-ce-*.rpmyum localinstall的好处是它会读取当前目录下所有 rpm 的依赖信息,自动决定安装顺序,并在缺包时给出明确提示。缺点是如果这台机器本身 yum 源配置有问题,它可能会尝试访问网络源然后超时;离线环境里建议先配置一个空的本地源或者直接断开网络等超时结束。
方法二更可控,适合批量部署场景。把三个 rpm 拆成三条命令,哪一步失败看得清清楚楚。安装完成后不要急着起服务,先确认可执行文件存在:
which dockerd docker containerd还有一种常见做法是直接用官方静态二进制包,解压后把 docker、dockerd、containerd 拷到 /usr/bin,再手写一个 systemd 服务。这种方式不碰 rpm 依赖,适合精简系统,但后续升级和卸载全靠自己维护,systemd service 文件也要自己写,踩坑空间不小。我一般只在对 rpm 生态完全不熟悉的目标机上才用,常规 CentOS 7 环境还是走 rpm 路线更省心。
3. 一键部署脚本与 daemon.json 的三个必调参数
3.1 部署脚本骨架:从装包到起服务,一条命令跑完
离线部署工具里最值钱的部分是一份经过验证的部署脚本。它做的事不多:装 rpm、写配置、起服务、导镜像、校验结果。但每一步的失败处理都要提前想好。下面这份脚本是我在离线项目里常用的骨架:
#!/usr/bin/env bash # docker19.03.9 离线部署脚本 set -Eeuo pipefail PKG_DIR="/opt/docker-offline/packages" IMG_TAR="/opt/docker-offline/images.tar" DATA_ROOT="/data/docker" for cmd in tar rpm systemctl; do command -v "$cmd" >/dev/null || { echo "缺少命令: $cmd"; exit 1; } done echo "[1/5] 安装 rpm 包" cd "$PKG_DIR" rpm -Uvh containerd.io-*.rpm rpm -Uvh docker-ce-cli-*.rpm rpm -Uvh docker-ce-*.rpm echo "[2/5] 写入 daemon.json" mkdir -p /etc/docker cat >/etc/docker/daemon.json <<'EOF' { "data-root": "/data/docker", "log-driver": "json-file", "log-opts": {"max-size": "50m", "max-file": "3"}, "live-restore": true } EOF echo "[3/5] 启动 docker" systemctl enable --now docker systemctl is-active docker || { journalctl -u docker -n 50; exit 1; } echo "[4/5] 导入镜像" if [ -f "$IMG_TAR" ]; then docker load -i "$IMG_TAR" fi echo "[5/5] 校验" docker version --format 'server: {{.Server.Version}}' docker info --format 'root: {{.DockerRootDir}} driver: {{.Driver}}'set -Eeuo pipefail这行不是装饰。-e让脚本在 rpm 安装失败时立刻退出,-u能在变量名拼错时直接报错,pipefail保证管道中任何一环失败都会被捕捉到。离线批量部署最怕的就是脚本“半成功半失败”地往下走,最后每台机器状态都不一样。
rpm 安装部分没有在一行命令里用通配符装全部包,而是拆成三条,原因是 containerd.io、cli、docker-ce 三者有严格依赖顺序,合并成一条虽然也能装,但失败时定位不到具体是哪一层出的问题。daemon.json 写入用的是 heredoc 方式,比 echo 拼接字符串靠谱得多,JSON 文件里的引号和逗号不用转义。
3.2 daemon.json 参数逐项拆解:哪些必调、哪些容易翻车
daemon.json 是 Docker 守护进程的配置文件,离线场景下我建议至少调下面几个参数。先看完整示例:
{ "data-root": "/data/docker", "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": {"max-size": "50m", "max-file": "3"}, "storage-driver": "overlay2", "live-restore": true, "insecure-registries": ["192.168.10.20:5000"] }每个字段的作用和适用场景,我整理了一张参数表:
| 参数 | 离线环境建议 | 选型理由 |
|---|---|---|
| ># 数据目录检查与创建 if [ ! -d "$DATA_ROOT" ]; then mkdir -p "$DATA_ROOT" fi df -h "$DATA_ROOT" | awk 'NR==2{if ($4 ~ /G/) {size=+$4} print $4}' 如果部署时这台机器已经有正在运行的旧 Docker,改># 在有网机器上,把多镜像打成一个 tar docker save -o /data/offline-images.tar \ nginx:1.19.10 \ app/web:v2.0.1 # 在目标机上导入 docker load -i /data/offline-images.tar 两个细节值得特别说明。第一,docker save 支持在一个命令里导出多个镜像,tar 文件会更大但导入效率高,目标机只需执行一次 load。第二,save 的对象必须写仓库名和 tag,即 离线镜像 tar 的命名规范我建议在团队里统一,比如 4.2 内网 registry 自建:registry:2 启动、push 与证书如果离线环境不只是单台机器,而是几十台机器都要拉同一个镜像,docker save/load 逐台拷包就不划算了。常见做法是自建一个内网 registry。最简单的方案是用 registry:2 镜像跑一个容器: 启动之后,把要分发的镜像打上内网地址的 tag 再 push: 这里有个很容易踩的配置点。如果内网 registry 没有配 HTTPS 证书,docker push 会报 registry:2 适合镜像不多、不需要权限管理的场景。如果离线环境要支撑几十个项目和团队,Harbor 更合适,但它自身依赖 PostgreSQL、Redis 等组件,离线部署时要额外准备一批镜像和配置,复杂度高出不少。先跑通 registry:2 再评估要不要上 Harbor,是最稳的推进路径。 5. 离线部署避坑:依赖错位、镜像掉 tag 与内核存储驱动5.1 libseccomp 过旧:hello-world 都跑不起来的典型信号遇到过最典型的一个现象:docker 装好了、服务也 active,执行 真实原因是 runc 需要系统 libseccomp 库提供较新的 seccomp 过滤能力。CentOS 7 早期最小化安装的机器上,libseccomp 版本可能停留在 2.3.1,而 Docker 19.03.9 绑定的 runc 在某些系统调用上需要更新的 seccomp 规则。检查方法: 如果版本低于 2.3.2,就在有网机器上抓一个 libseccomp 的升级包带进内网, 5.2 docker load 后全是 :save 的时候姿势就错了这个坑是离线交付里最隐蔽的:目标机执行 实际上问题不在 load,而在 save 那一步。如果导出时用的是 5.3 overlay2 起不来:XFS 的 ftype 与内核模块另一类高频故障是 dockerd 起不来,journalctl 里能看到 overlay 挂载失败或 检查当前分区是否支持: 如果输出 5.4 daemon.json 改完 daemon 起不来:语法与数据目录两层坑离线部署脚本最常被改的就是 daemon.json,改出问题的概率也最高。第一种情况是 JSON 语法错误。daemon.json 是严格要求合法 JSON 格式的文件,多一个逗号、少一个引号,dockerd 都会拒绝启动。19.03 版本对配置解析是硬校验,只要语法错,服务直接起不来。 这个问题在交付前就能拦截,方法是在有网机器上先校验: 第二种情况是前面提过的>systemctl stop docker rsync -a /var/lib/docker/ /data/docker/ systemctl start docker 这三行命令的顺序不能乱。先复制再改配置,启动后数据无缝衔接;改完配置再复制,新目录里没数据,容器列表自然为空。 6. 部署完别急着走:校验三连与排查顺序6.1 校验三连:version、info、images离线部署脚本跑完不是终点,机器要真正能跑容器才算交付完成。我在确认一台机器时习惯固定在三个命令,它们看的信息正好覆盖“服务在不在、配置对不对、镜像全不全”三个层面: 如果这三点都正常,再用一个业务镜像做冒烟测试,比如 6.2 出问题先看哪三处部署遇到问题时,我的排查顺序是固定的。第一看 这套脚本和校验命令我习惯放在离线包根目录下,命名为 本文还有配套的精品资源,点击获取 |