
简介在CentOS 7.6离线环境下部署容器服务时常因无法联网安装依赖而受阻。这份资源提供docker-ce 19.03与nvidia-docker2 2.4的完整离线安装包面向需要快速搭建GPU容器运行环境的运维或算法工程师解决无外网场景下的部署难题。压缩包共30个文件大小91.98MB包含20个rpm依赖包及gz、bz2、xml、json等辅助文件。其中docker-local目录内置docker-ce、containerd.io等引擎组件nvidia-docker2目录内置nvidia-container-toolkit、libnvidia-container等GPU容器工具链xml为repodata仓库元数据json为daemon配置模板另有gpg密钥与安装说明txt。已有3312人学习下载实用性受到认可。使用时将包整体拷贝至内网服务器按说明依次安装rpm并启用docker再用模板替换daemon.json并注意改路径重载systemd重启服务即可。流程清晰、依赖齐全能显著减少离线部署中的依赖排查与软件收集时间适合具备基础Docker概念的读者快速落地包内还附有验证安装结果的命令提示便于确认部署是否成功。1. CentOS 7.6 这台断网机器为什么要耗时间离线装 docker-ce 19.03 和 nvidia-docker2一台 CentOS 7.6 的 GPU 服务器放在隔离网段里没有外网、没有内网 yum 镜像却要跑 CUDA 容器。系统里本来什么都没有逼着你把 docker-ce-19.03 和 nvidia-docker2 用离线包一点点喂进去。第一次做这种活的人通常以为离线安装就是把 rpm 拷进去然后rpm -ivh真正上手才发现一半时间耗在 libseccomp 版本、nvidia-container-runtime 依赖和 daemon.json 被覆盖这种破事上。Docker 19.03 刚好是能安稳配 CentOS 7 老系列内核的版本nvidia-docker2 则负责把它跟 GPU 驱动接上。离线安装这种事装崩一次代价不小服务器在机房里你人在办公室每次出问题都得重新让同事帮忙插网线。下面这套流程是按“一次搬齐、本地仓库解析依赖、先镜像后验证”的路子做的照着走能避开绝大多数翻车点。2. 离线安装前先搭“搬运清单”yum 下载、依赖树和驱动版本三件事离线装 docker-ce 和 nvidia-docker2失败大多不是因为安装步骤不对而是搬运清单没列全。常见做法是先找一台能联网的 CentOS 7 机器把所有需要的 rpm 连依赖一起下载到本地再打个 tar 包传到目标服务器。这个阶段多花半小时能省下后面一整天的排查时间。2.1 在联网机器上用 yumdownloader 拉齐 docker-ce 19.03 的 rpm 全家桶先准备一个目录专门放离线包。联网机器要求是 CentOS 7 系列最好是干净系统避免本机装过其它版本的 docker 干扰解析结果。mkdir -p /tmp/docker-offline # 安装 yum-utils提供 yumdownloader yum install -y yum-utils # 添加 docker 官方源这里只做下载服务不安装 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo cd /tmp/docker-offline # 把 docker-ce 19.03 需要的包连依赖一次性下载 yumdownloader --resolve \ docker-ce-19.03.15-3.el7 \ docker-ce-cli-19.03.15-3.el7 \ containerd.io-1.2.13-3.2.el7 # 顺便把 createrepo 带上目标机器建本地 yum 仓库要它 yumdownloader --resolve createrepo这段命令的逻辑是--resolve让 yumdownloader 把每个指定包的依赖一起拉下来不单单拿主安装包。docker-ce 19.03 的 rpm 依赖 containerd.io 和 docker-ce-cli单独拷 docker-ce 一个文件过去到目标机器上 yum 解析依赖时会当场报错那才是真的叫天天不应。参数说明里有个关键点命令里写的是 19.03.15 的具体版本号不是docker-ce-19.03.*这种通配写法。yumdownloader 对通配版本号的支持在不同版本 yum 上表现不一致没匹配到时它会报 “No matching packages”很低级的坑。如果官方源里 19.03.15 已经找不到可以yum list docker-ce --showduplicates | grep 19.03看可用的小版本号选最后一个 19.03.x 即可。下载完检查一下目录除了上面三个包还会多出 libtool-ltdl、container-selinux、libseccomp 这些依赖这些都是正常的。如果container-selinux没被自动拉进来说明在线机的 extras 源没启用手动补一条yumdownloader --resolve container-selinux。这个包在 CentOS 7 的 extras 仓库里目标机器通常没有漏掉它 docker-ce 的 RPM 依赖检查会直接失败。2.2 把 nvidia-docker2 的依赖树排干净再决定带哪个版本docker-ce 装完接着搬 nvidia-docker2。这一组 rpm 来自 NVIDIA 的 libnvidia-container 仓库常用做法是先把仓库配置文件加入在线机再用同一个 yumdownloader 命令下载。cd /tmp/docker-offline # 加入 NVIDIA 容器运行时仓库 yum-config-manager --add-repo https://nvidia.github.io/libnvidia-container/centos7/libnvidia-container.repo yumdownloader --resolve \ nvidia-docker2-2.5.0-1.x86_64 # 拷到目标机之前打个压缩包 cd /tmp tar czf docker-offline.tgz docker-offlinenvidia-docker2 的依赖树比 docker-ce 稍微绕一点。它本身是个“包装包”安装脚本负责把/etc/docker/daemon.json里的 runtime 字段补上真正起作用的是它依赖的 nvidia-container-runtime而 nvidia-container-runtime 又依赖 nvidia-container-toolkittoolkit 再依赖 libnvidia-container1 和 libnvidia-container-tools。这一串少任何一个容器里都见不到 GPU 设备。离线包里这些 rpm 本身都是相互依赖的必须一起进入同一个目录。下表列一下这组包各自的作用搬运时按表核对就不会漏包名作用备注nvidia-docker2总入口postinstall 脚本改 daemon.json版本锁 2.5.0nvidia-container-runtime被 Docker 调用的运行时入口nvidia-docker2 的直接依赖nvidia-container-toolkit生成运行时配置负责挂载 GPU 设备多数问题出在这一层libnvidia-container1底层库执行设备挂载动作需要和 toolkit 版本匹配libnvidia-container-toolscli 工具提供 nvidia-container-cli排查时要用它版本匹配是这里的玄学点nvidia-docker2 2.5.0 与 docker-ce 19.03 是同一时期的组合配套很稳。如果联网机器上“顺手”装的是新版 docker-ce 24.x再带 nvidia-docker2 2.6 或 2.7到离线机器上会有一堆隐性问题比如 daemon.json 的 schema 对不上。所以我在落地时会把版本全部锁定宁可旧一点不赌兼容性。2.3 先把目标机的 uname -r 和驱动版本记下来离线包才有意义离线包本身不包含 GPU 驱动。nvidia-docker2 只做一件事在容器启动时把宿主机已安装的 NVIDIA 驱动目录和设备文件挂载进容器。宿主机没有驱动装再完整的 nvidia-docker2 都是白搭。所以搬运清单里真正关键的一项是目标服务器上现有驱动的版本和内核版本。在目标机上先执行uname -r nvidia-smi ls -l /dev/nvidia0 /dev/nvidiactl把uname -r的输出记下来对照下载驱动包时需要的内核版本nvidia-smi能正常输出显卡型号和驱动版本才说明内核模块加载成功。/dev/nvidia0和/dev/nvidiactl这两个设备文件通常由 driver 的 udev 规则自动创建如果它们不存在即使nvidia-smi能出结果容器挂载 GPU 时也可能拿不到设备节点。我见过一个很典型的翻车场景同事拿了一台“装过驱动但没重启”的服务器nvidia-smi报错找不到设备他以为是驱动坏了重装 nvidia-docker2 三遍都没用。实际上重启后内核模块加载好问题自动消失。所以离线开工前先把这一条当作前置门槛写进 checklist目标机的驱动必须已经能在宿主机上跑通 nvidia-smi否则后面步骤都不用做。另外把目标机的磁盘空间看一眼。rpm 包压缩后大概 100 到 200MB但后面还要放 docker 镜像 tar镜像动辄几个 GB。离线目录建议放在/data或其它大分区下别把/tmp塞炸。3. 离线安装 docker-ce-19.03本地 yum 仓库、daemon.json 与启动验证到这一步tar 包已经传到目标机器。接下来不急着rpm -ivh先把目录变成 yum 本地仓库让 yum 自己处理依赖顺序。这个选择能省掉很多手动排依赖的麻烦特别是后面 nvidia-docker2 那组相互依赖的包yum 事务一次性装完手动 rpm 装会卡在循环依赖上。3.1 把 rpm 目录变成 local yum 仓库让 yum 自己解析依赖解包后先建仓库元数据再写一个只指向本地目录的 repo 文件。mkdir -p /data/docker-offline tar xzf docker-offline.tgz -C /data/docker-offline --strip-components1 # createrepo 离线安装 rpm -Uvh /data/docker-offline/createrepo*.rpm /data/docker-offline/python-deltarpm*.rpm /data/docker-offline/deltarpm*.rpm # 生成仓库元数据 createrepo /data/docker-offline # 写本地仓库配置 cat /etc/yum.repos.d/offline.repo EOF [offline] nameOffline Docker CE 19.03 baseurlfile:///data/docker-offline enabled1 gpgcheck0 EOF建仓库这一步有个细节先rpm -Uvh装 createrepo 时可能报缺少python-deltarpm所以我把 deltarpm 相关的三个包放在同一条命令里让 rpm 在一次命令里装完。如果目标机器有yum install createrepo的条件也可以直接用 yum但离线场景下通常没有这个条件手装是最稳的。repo 文件里gpgcheck0是偏离默认安全配置的做法但在内网离线环境没有导入 GPG key 的路径很多团队都是关掉校验先装上。讲究一点的可以在线机上把 Docker 和 NVIDIA 的 GPG key 文件导出放到 repo 目录里再配上gpgkeyfile:///data/docker-offline/RPM-GPG-KEY-*实现完整校验。后一种做法更严谨内网安全要求高的时候值得做。建好仓库后先验证一下 yum 能不能识别这些包yum --disablerepo* --enablerepooffline list docker-ce-19.03.15-3.el7这一步能看到就说明仓库没问题。随后正式安装 docker-ce 全家桶yum install -y --disablerepo* --enablerepooffline \ docker-ce-19.03.15-3.el7 \ docker-ce-cli-19.03.15-3.el7 \ containerd.io-1.2.13-3.2.el7命令里的--disablerepo* --enablerepooffline是关键保护。目标机器的 /etc/yum.repos.d 里通常还有 CentOS-Base.repo 之类的文件如果不去禁用yum 会把 CentOS 自带的 docker 1.13 当成候选解析对象安装时就会出现冲突这个坑在后面专门展开。这里只要记得离线真机上装东西只用 offline 这一个源。3.2 安装 docker-ce 19.03 后立即配置 daemon.json安装完成后先别急着启动docker 默认的 daemon.json 还不存在先按自己的目录规划写好配置。mkdir -p /etc/docker /data/docker-root cat /etc/docker/daemon.json EOF { data-root: /data/docker-root, log-driver: json-file, log-opts: { max-size: 50m, max-file: 2 } } EOF systemctl start docker systemctl enable dockerdaemon.json 里的># 目标机上执行 docker load -i /data/docker-images/busybox.1.36.tar docker run --rm busybox:1.36 sh -c echo docker-ok如果这条命令能输出docker-ok说明 containerd、runc、docker daemon 三层链路都通了。busybox 镜像只有几 MB加载速度快占用空间也小适合做第一个冒烟测试。这一步通过后再进 nvidia-docker2 的安装别跳级。4. 离线安装 nvidia-docker2前置驱动、容器运行时和 GPU 验证一条链nvidia-docker2 装上后docker 才有能力把宿主机的 GPU 设备挂进容器。但这条链是串起来的宿主机驱动、libnvidia-container 库、docker 运行时配置、容器镜像任何一环断了表现都是“容器里用不了 GPU”。下面按顺序走。4.1 先确认宿主机的 nvidia-smi 可用再谈 nvidia-container-runtime第二章已经说过离线包里没有驱动。这一节再补一个容易漏的点驱动装好不等于 nvidia-smi 能用。有些服务器的驱动包是通过dkms编译的内核升级后模块没自动重建nvidia-smi就会报couldnt communicate with the NVIDIA driver。实际操作上装 nvidia-docker2 前再跑一次宿主机验证nvidia-smi # 期望输出 GPU 型号、驱动版本、CUDA 版本看到正常输出后顺手确认一下nvidia-container-cli工具是否可用。这个工具在 libnvidia-container-tools 包里它负责真正的设备挂载安装完 nvidia-docker2 以后用它检查 GPU 可见性比直接跑容器快得多。nvidia-container-cli info这条命令会输出 GPU 数量、驱动库路径、设备文件权限这些信息。如果它报权限错误或找不到库文件先解决这些问题再继续。它跑不通容器里连nvidia-smi的边都摸不到。这一步是后面所有排查的锚点。4.2 离线安装 nvidia-docker2 的 rpm并让 docker daemon 认这个 runtime确认宿主机 GPU 正常后用本地仓库把 nvidia-docker2 一组包装进去。yum install -y --disablerepo* --enablerepooffline nvidia-docker2-2.5.0-1.x86_64装完看 /etc/docker/daemon.json正常情况下会多出 runtimes 字段{ data-root: /data/docker-root, log-driver: json-file, log-opts: { max-size: 50m, max-file: 2 }, runtimes: { nvidia: { path: nvidia-container-runtime, runtimeArgs: [] } } }如果 daemon.json 里没有这段可以手动补上。然后重启 docker 让它生效systemctl restart docker # 确认 nvidia runtime 已被 docker 识别 docker info | grep -i -A2 runtime这里有个取舍要讲清楚daemon.json 里只是注册了 nvidia 这个运行时并没有把默认运行时改成 nvidia。这样普通容器默认用 runc不带 GPU 能力只有显式指定--gpus或--runtimenvidia的容器才有 GPU。如果业务上希望所有容器默认可见 GPU可以加一行default-runtime: nvidia但我不建议这么做会让普通容器也背着 GPU 挂载的开销而且在共享机器上容易造成 GPU 内存分配混乱。Docker 19.03 已经支持--gpus参数它本质上还是调 nvidia-container-runtime 完成挂载。所以 19.03 时代用--gpus all和--runtimenvidia是并行的两条路后面验证时两种都跑一遍最保险。4.3 离线环境里怎么验证 GPUdocker load 一份 CUDA 镜像再说容器镜像本身不在离线包里得在联网机上准备好带 CUDA 运行时的镜像比如常见的 nvidia/cuda:10.0-base导出成 tar 再传过去。这一步最好在安装前就规划好因为 GPU 验证绕不开一个具体的 CUDA 镜像。联网机上先做docker pull nvidia/cuda:10.0-base docker save nvidia/cuda:10.0-base -o cuda-10.0-base.tar然后把 tar 传到目标机加载并跑 GPU 验证docker load -i cuda-10.0-base.tar # 方式一19.03 原生 --gpus 参数 docker run --rm --gpus all nvidia/cuda:10.0-base nvidia-smi # 方式二显式指定 nvidia runtime docker run --rm --runtimenvidia nvidia/cuda:10.0-base nvidia-smi两条命令只要有一条能输出 GPU 信息就算通过。注意输出里要看两块内容一是显卡型号和驱动版本二是容器里的nvidia-smi路径是否正常。如果第一条报could not select device通常意味着 docker 19.03 的--gpus参数没有正确关联到 nvidia-container-runtime这时改用--runtimenvidia验证能过就说明运行时本身没问题只是参数传递路径有差异。如果两条都失败回到 4.1 的nvidia-container-cli info检查别在容器层面上反复折腾。我踩过最深的一次就是这个顺序问题花了一晚上换各种 CUDA 镜像 tag最后发现是宿主机的 libnvidia-container 和驱动版本不匹配nvidia-container-cli info直接报错跟容器镜像完全没关系。5. 离线安装的 5 个常见问题yum 源、libseccomp、daemon.json 覆盖整个流程做完已经很顺但真正到别人的机器上操作时各种环境残留会导致怪问题。下面五条是按异常频率排的每一条都是“现象 → 原因 → 解决”式排查直接对号入座。5.1 现象一docker 服务起不来日志里报 libseccomp.so.2 版本不对现象systemctl start docker失败journalctl -u docker里看到version LIBSECCOMP_2.4 not found或者 dockerd 直接报error initializing seccomp support。原因离线机器用的 CentOS 7.6 自带的 libseccomp 是 2.3.1而搬运来的 docker-ce 是最新版本不是 19.03。新版本 docker 20.10 以后编译时要求 libseccomp 至少 2.4和系统库版本对不上。docker-ce 19.03 正好是卡在 2.3.1 上的版本只要锁对版本就不会触发这个问题。解决重新在联网机上按 2.1 的命令下载 docker-ce-19.03.15-3.el7 全家桶覆盖离线包。注意 docker-ce-cli 和 containerd.io 也要用同期版本整体版本错位才能跑得起来。如果业务上确实需要新版本 docker那就得另外把 CentOS 7 的 libseccomp 升级到 2.4这通常要连带升级一堆依赖离线情况下代价偏大不如锁 19.03。5.2 现象二nvidia-docker2 装好了容器里却找不到 nvidia-smi现象docker run --rm --gpus all nvidia/cuda:10.0-base nvidia-smi报nvidia-smi: not found但宿主机上 nvidia-smi 工作正常。原因三层问题从高到低排查。第一层daemon.json 里 runtimes 字段没写对docker 没认出 nvidia 运行时第二层nvidia-container-toolkit 版本和 libnvidia-container 不匹配挂载动作没真正执行第三层镜像本身是全量镜像但缺少 nvidia-smi 的符号链接这种情况在非官方 CUDA 镜像里很常见。解决先在宿主机跑nvidia-container-cli info它正常说明前两层没问题。然后换回官方nvidia/cuda:10.0-base并且用--runtimenvidia绕开--gpus路径再试一次。两条都正常但还是 not found进容器看/usr/bin/nvidia-smi是否存在docker run --rm --entrypoint ls nvidia/cuda:10.0-base -l /usr/bin/nvidia-smi。没有的话基本可以确定是镜像 tag 太偏换成官方 CUDA base 即可。5.3 现象三重启 docker 后daemon.json 里的 nvidia runtime 被还原了现象手工写了 daemon.json加了 runtimes 字段重启 docker 后docker info里没有 nvidia 运行时文件里自己写的># 联网机 docker pull nvidia/cuda:10.0-base docker pull busybox:1.36 docker save nvidia/cuda:10.0-base -o cuda-10.0-base.tar docker save busybox:1.36 -o busybox.1.36.tardocker save比docker export合适的点在于它会保留镜像的历史层和元数据load 回去之后还能基于它重新打 tag 或做 COMMITexport 出来的 tar 只是文件系统快照丢失了这些信息。两个镜像打完和离线 rpm 包放同一个目录一起传输即可。6.2 目标机上 docker load 并跑通完整的 GPU 推理验证镜像到达目标机后先 load 再验证验证输出最好留一份当场记录docker load -i cuda-10.0-base.tar docker load -i busybox.1.36.tar # 输出到文件留作交付依据 docker run --rm --gpus all nvidia/cuda:10.0-base nvidia-smi /data/gpu-verify.txt cat /data/gpu-verify.txt看输出文件里的 Driver Version 和显卡型号再确认容器里的 CUDA 版本能匹配业务需求。如果业务侧实际用的是 CUDA 11 或 CUDA 12就让联网机提前拉对应版本的 base 镜像验证命令不变只换镜像 tag。验证做完这套环境才算真正交付。6.3 把离线安装过程固化成 install.sh 和 verify.sh下次不再靠回忆经验越多的离线项目越应该把流程写成脚本因为第二次安装往往是几个月后那时的你已经忘光了 daemon.json 里的细节。下面这段脚本是按本文流程浓缩的可以直接存成 install.sh#!/usr/bin/env bash set -euo pipefail OFFLINE_DIR${1:-/data/docker-offline} REPO_NAMEoffline # 建本地仓库 createrepo $OFFLINE_DIR cat /etc/yum.repos.d/${REPO_NAME}.repo EOF [${REPO_NAME}] nameoffline-docker baseurlfile://${OFFLINE_DIR} enabled1 gpgcheck0 EOF # 安装 docker-ce 19.03 nvidia-docker2 yum install -y --disablerepo* --enablerepo${REPO_NAME} \ docker-ce-19.03.15-3.el7 docker-ce-cli-19.03.15-3.el7 \ containerd.io-1.2.13-3.2.el7 nvidia-docker2-2.5.0-1.x86_64 # 配置 daemon.json保留已有配置 if [ -f /etc/docker/daemon.json ]; then cp /etc/docker/daemon.json /root/daemon.json.bak fi systemctl enable --now docker docker info脚本化最大的好处是排除个人操作差异。不同人手动装的时候可能一个漏了--disablerepo一个漏了备份交付质量全凭状态。脚本里set -euo pipefail能保证任何一步失败就停下不再继续往下装避免装到一半还硬着头皮重启服务的局面。回头看我做过的离线交付项目最值钱的经验不是某个 rpm 版本号而是一份完整的“镜像清单 验证步骤”。装机的人换了一茬又一茬只要照着这份清单半天内总能复现同一套环境。装完以后把镜像 tar 和代码块都归档到固定的目录下次整机迁移时直接把整个目录拷走就行比重新下载省事得多。希望帮到你。本文还有配套的精品资源点击获取