
简介面向需要在无网络的内网环境中为GPU服务器部署容器服务的运维工程师与算法工程师该资源提供了在 CentOS 7.6 上离线安装 docker-ce 19.03 与 nvidia-docker2 2.4 的完整依赖包、配置模板和实施说明。资源共30个文件压缩包约92MB核心为20个rpm安装包涵盖docker、containerd、nvidia-container-toolkit等必要组件其余为gz、bz2等依赖压缩文件、仓库元数据xml、daemon.json配置文件、txt格式说明文档以及gpg校验文件其中daemon.json为数据存储路径配置示例可根据实际磁盘规划调整后使用。这些文件已按安装依赖关系组织且docker相关rpm与nvidia组件分目录存放目录结构清晰便于离线分发与批量部署。目前已有3312人学习下载适合需要搭建GPU容器环境或进行离线迁移的读者。利用该资源可免去在无外网环境逐一收集依赖的繁琐过程同时获得路径替换示例帮助快速完成Docker与GPU加速容器运行环境的离线部署降低安装失败概率。1. 离线装 Docker 19.03 nvidia-docker2一次搞定依赖树的完整方案centos7.6 离线安装 docker-ce-19.03 和 nvidia-docker2难点从来不在 Docker 本身而在依赖树和 NVIDIA 容器运行时那套兼容关系。没有外网的机器上yum 装不上任何东西rpm 手动装又常被依赖顺序卡住更别提 nvidia-docker2 装完还得验证 GPU 能不能真正透传进容器。这套东西适合正在做内网部署、GPU 服务器交付、或者给客户做离线环境初始化的工程师照着做能把从依赖打包到nvidia-smi进容器的链路一次打通。我下面把整个流程拆成攒包、装 Docker、装 nvidia-docker2、验证四段讲每段都带上实际用的命令和踩过的坑。2. 攒离线安装包在联网机器上准备完整依赖树离线安装 Docker 的第一步不是上目标机器操作而是找一台能联网、系统版本一致的机器把所有依赖包下载齐全。常见做法是 yumdownloader 配合 createrepo 构建本地 Yum 仓库比逐个 rpm 硬装稳得多——后者一旦遇到依赖递归很容易陷入“缺 A 装 AA 又缺 B”的死循环。2.1 安装 createrepo 并准备下载目录联网机器上先确认能访问 CentOS 7 的 base、extras、docker-ce 官方仓库然后装 createrepo 工具# 联网机器上执行 yum install -y createrepo mkdir -p /opt/docker-offline/{rpms,repo} cd /opt/docker-offline/rpmscreaterepo 用来生成 Yum 仓库元数据目标机器加上这个本地仓库后就能用yum install走正常流程装包自动处理依赖顺序。目录结构上rpms 放下载的 rpm 文件repo 放 createrepo 生成的 repodata方便后面做仓库根目录。2.2 用 yumdownloader 拉取 docker-ce 和依赖包19.03 版本的 docker-ce 依赖 containerd.io、container-selinux、runc 等包这些都要一并下载# 先装 yum-utils提供 yumdownloader 命令 yum install -y yum-utils # 添加 docker-ce 官方仓库本机不安装只用来解析依赖 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 下载 docker-ce-19.03.x 及全部依赖 yumdownloader --resolve docker-ce-19.03.15-3.el7.x86_64--resolve参数会把 docker-ce 依赖的所有包一并拉下来这是离线安装能不能成功的关键。如果目标机器是 centos7.6建议下载 7.x 对应的 rpm不要混用 el8 的包。下载完成后检查一下目录里有没有 containerd.io、container-selinux、runc 这几个包缺了后面装 docker-ce 时会报依赖错误。2.3 拉取 nvidia-docker2 相关包nvidia-docker2 本质是个元包真正干活的是 nvidia-container-runtime 和 nvidia-container-toolkit# nvidia-docker2 源 curl -s -L https://nvidia.github.io/nvidia-docker/centos7/nvidia-docker.repo \ -o /etc/yum.repos.d/nvidia-docker.repo yumdownloader --resolve nvidia-docker2-2.6.0-1.x86_64这里有个版本匹配问题nvidia-docker2 2.x 对应 toolkit 1.x新版 2.7 才开始对应 toolkit 1.4装完配置写法也有差异。用 2.6.0 这个版本和 docker-ce 19.03 搭配是比较稳的组合新版本在 19.03 上也能跑但需要额外处理 nvidia-container-runtime-hook 的兼容参数。2.4 生成 Yum 仓库元数据所有 rpm 下载完成后生成仓库索引# 把 rpms 目录下所有 rpm 收集到 repo 目录 cd /opt/docker-offline cp rpms/*.rpm repo/ # 生成仓库元数据 createrepo --update repo/createrepo 生成的 repodata 目录是目标机器yum install时依赖的索引文件没有它目标机器的 Yum 只看到一堆 rpm 文件没法解析依赖。参数--update在重复执行时可以增量更新不用每次全量重建。2.5 打包传输到目标机器把整个 docker-offline 目录压缩传输到内网机器路径随意但建议固定# 联网机器上压缩 tar -czf docker-offline.tar.gz docker-offline/ # 传到目标机器后解压比如解压到 /opt/docker-offline tar -xzf docker-offline.tar.gz -C /opt/注意点依赖包里如果有 epel-release 的包源里会多出 epel 的仓库文件如果还缺其他包最稳妥的做法是在联网机器上预先yum install --downloadonly跑一遍把缺的都补齐。我当时就在这一步吃过亏只下 docker-ce 主包结果装的时候报 container-selinux 版本不够来回折腾了两轮。3. 目标机器安装 Docker CE本地仓库替代外网源目标机器上所有安装操作都走本地 Yum 仓库不再触碰外网。这里把第 2 章生成的 repo 目录挂为仓库然后用 yum 正常安装。3.1 配置本地 Yum 仓库先备份原有 repo 文件避免遗留的远程源导致 Yum 卡在超时上# 备份原有 repo mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/ # 写本地仓库配置 cat /etc/yum.repos.d/local-docker.repo EOF [local-docker] nameLocal Docker Offline Repo baseurlfile:///opt/docker-offline/repo enabled1 gpgcheck0 EOFgpgcheck0是离线环境下的必要设置因为本地方没有导入 GPG key检查会直接报错。完全物理隔离的机器上不需要安全来源验证信任的是你自己打的包。如果有安全合规要求可以在联网机器上导出 Docker 官方 GPG key传到目标机后导入但操作成本高多数离线部署并不会这么做。3.2 安装 docker-ce配置好仓库后直接安装 docker-ce# 清理缓存后重新构建 yum clean all yum makecache # 安装 docker-ce不指定版本按仓库里唯一的 19.03 版本走 yum install -y docker-ce这一步会自动解析 containerd.io、container-selinux、runc 的依赖关系。如果第 2 章下载依赖时漏了某个包这里就会报Error: Package: docker-ce-19.03.15-3.el7.x86_64 requires: xxx缺什么回联网机器补什么即可不用卸载重来。3.3 配置 daemon.json安装完成后先别急着 start把 Docker 的运行时参数写进配置文件mkdir -p /etc/docker cat /etc/docker/daemon.json EOF { exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, storage-driver: overlay2, data-root: /data/docker } EOFcgroupdriver 用 systemd 是为了和 kubelet 保持一致后面如果接 Kubernetes这里没配对会导致节点状态异常。storage-driver 用 overlay2前提是内核支持centos7.6 默认 3.10.0-957 内核是支持的但 xfs 文件系统需要 d_type 支持格式化时没开 ftype1 会报错遇到这个下文第 4 章会细说。data-root 按实际需要改这个参数在离线环境里尤其重要——如果磁盘分区规划没提前做Docker 默认目录写满根分区是常见事故。3.4 启动 Docker 并设置开机自启systemctl daemon-reload systemctl start docker systemctl enable docker启动完成后确认状态systemctl status docker docker versiondocker version能看到 Client 和 Server 两段信息Server 段正常输出就说明 daemon 起来了。如果只看到 Client 信息、没有 Server 段多半是 daemon 启动失败用journalctl -u docker看具体日志。4. nvidia-docker2 安装避坑常见问题与排查记录nvidia-docker2 的坑明显比 docker-ce 多。我在不同机器上装过好几轮这里把碰到的高频问题按现象、原因、解决方式记录基本都是内网环境特有的问题。4.1 问题一rpm 安装 nvidia-docker2 时 GPG key 校验失败现象在本地仓库安装 nvidia-docker2报NOKEY错误或Public key for nvidia-container-runtime-*.rpm is not installed。原因第 2 章打包 nvidia-docker2 依赖时没导入 NVIDIA 的 GPG key本地仓库gpgcheck0只对 docker-ce 生效如果 nvidia 的 rpm 是被单独的 yum 源管理的依然会启用 key 校验。解决打包时一并导出 NVIDIA 的 GPG key或者安装时跳过校验。# 在联网机器上导出 GPG key gpg --export --armor KEY_ID nvidia.asc # 传到目标机器后导入 rpm --import nvidia.asc # 或者直接安装时忽略 GPG yum install -y --nogpgcheck nvidia-docker2-2.6.0实际部署中我一般直接在本地仓库配置里保持gpgcheck0这样最省事。但如果客户有安全审计要求导出 key 导入是更正规的做法。4.2 问题二nvidia-container-runtime 启动报找不到 libnvidia-container.so.1现象docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi报错exec: nvidia-smi: executable file not found in $PATH或libnvidia-container.so.1: cannot open shared object file。原因nvidia-container-toolkit 和 nvidia-container-runtime 版本不匹配或者 toolkit 安装不完整。nvidia-docker2 元包会拉取 toolkit但某些 rpm 依赖组合下 toolkit 的 so 文件路径不被 runtime 识别。解决确认 toolkit 版本链路有没有断掉重装 nvidia-container-toolkitrpm -qa | grep nvidia-container yum install -y nvidia-container-toolkit-1.4.8重点检查nvidia-container-toolkit和nvidia-container-runtime版本2.6.0 元包默认依赖 1.4.8 的 toolkit版本对不上就会出现 so 文件缺失。这种情况在离线环境下很常见因为打包时依赖解析把两个包的版本搞成了不兼容组合。4.3 问题三daemon.json 里配置 nvidia runtime 后 Docker 启动失败现象配置了runtimes: {nvidia: {path: /usr/bin/nvidia-container-runtime}}执行systemctl start docker报错。原因nvidia-container-runtime 可执行文件路径不对或者二进制依赖的库文件缺失。centos7.6 上常见问题是把 runtime 路径写成 hook 路径两个文件不是一个东西。解决先确认路径再写配置which nvidia-container-runtime ls -l /usr/bin/nvidia-container-runtime我实际操作中遇到过一次which有输出但启动失败的情况原因是运行时依赖libnvidia-container.so.1在升级 toolkit 时被覆盖成了新版本和 runtime 编译期依赖的版本不一致。解决方法是重装一遍 nvidia-container-runtime或者用 ldd 检查依赖再针对性补齐。4.4 问题四overlay2 存储驱动报错 d_type 不支持现象Docker 启动正常但创建容器报error creating overlay mount ... d_type not supported。原因/data/docker 所在分区是 xfs 且格式化时没开启 ftype1。centos7.6 的默认 xfs 格式化参数在部分内核版本上不启用 ftype导致 overlay2 无法工作。解决离线环境下没法重新格式化数据盘的最简单的方案是换用vfs存储驱动就是性能差点。有条件重新格式化磁盘的格式化命令里显式加参数mkfs.xfs -f -n ftype1 /dev/sdb1这块我踩得比较深第一次交付时图省事直接把 docker 数据目录放根分区结果根分区是默认 xfs 没开 ftype所有容器起不来。后来和客户协调重新挂了一块盘用 ftype1 格式化才解决。5. 验证 GPU 透传容器里跑 nvidia-smi 和 CUDA 测试装完 Docker 和 nvidia-docker2最后一步是验证 GPU 能不能真正从宿主机透传到容器。这一步不能省——很多机器装完一切正常但一跑 GPU 负载就曝出驱动版本不匹配的问题全在 nvidia-smi 的输出里体现。5.1 确认宿主机 GPU 驱动与 Docker 状态先看宿主机驱动是否正常nvidia-smi输出里注意驱动版本和 CUDA 版本。docker-ce 19.03 对 NVIDIA 驱动的硬性要求是 418.81.07 以上低于这个版本的驱动即使容器能起--gpus参数也不会生效。centos7.6 上常见的 410 或 415 版本驱动必须升级否则下面所有验证步骤都是白费。5.2 用基础 CUDA 镜像验证 GPU 透传拉取一个能联网下载的 CUDA 基础镜像这里假设内网有镜像仓库或者提前在联网机器上把镜像打成 tar 传了进来# 直接跑 GPU 容器 docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi这行命令如果能在容器里正常打出 GPU 列表整个链路就是通的。注意这里的--gpus all是 docker-ce 19.03 之后才有的参数老版本只支持--runtimenvidia写混了会直接报错。实际部署中遇到客户还在用 18.09 的 docker就得回退到--runtimenvidia的写法。5.3 更完整的验证跑一个实际的 CUDA 计算样例nvidia-smi 验证的是设备可见性计算路径是否通畅还需要跑一次 CUDA 运算docker run --rm --gpus all nvidia/cuda:11.0-base \ nvcc --versionnvcc --version能输出 CUDA 编译器的版本信息确认容器内 CUDA 工具链可用。如果这一步过了后续跑 PyTorch、TensorFlow 容器基本不会在系统层面出问题。之前遇到过容器里 nvidia-smi 正常但 PyTorch 报 CUDA error原因是宿主机驱动版本编译的 CUDA 和镜像里的 CUDA 主版本不兼容这类问题要在部署规划阶段确定镜像 CUDA 版本和宿主机驱动支持的 CUDA 版本的匹配关系。5.4 验证 Docker 的 NVIDIA runtime 配置生效docker info | grep -A 5 Runtimes输出里Runtimes: nvidia出现说明 daemon 已加载 nvidia 运行时。如果这里没有 nvidia后面--gpus参数会出现Unknown runtime specified: nvidia的报错。6. 离线环境下的进阶技巧镜像搬运与 GPU 资源管理安装和验证打通之后落地到生产环境还有几个常用的技巧值得提前准备。第一个是镜像的离线搬运——内网机器没有外网镜像要么通过docker save和docker load传输要么搭一套私有镜像仓库。docker save对于大镜像比如 PyTorch 的容器动辄 5GB 以上可以直接用# 联网机器上保存镜像 docker save nvidia/cuda:11.0-base | gzip cuda11-base.tar.gz # 目标机器上加载 gunzip -c cuda11-base.tar.gz | docker load这个方式适合一次性交付的场景多次更新镜像就用私有仓库——docker registry 容器本身也可以在离线环境里跑起来回传端口 5000 就能对外服务。我一般会在目标机器上把 registry 容器和 Docker 一起部署后续所有镜像都走内网 push/pull省去反复 save/load 的传输成本。第二个技巧是 GPU 资源的细粒度管理。--gpus all是开发环境的懒人选项生产环境要给容器分配指定 GPU# 只透传 GPU 0 和 GPU 1 docker run --rm --gpus device0,1 nvidia/cuda:11.0-base nvidia-smi用device0,1这个 JSON 字符串语法而不是--gpus 2能精确控制哪张卡进容器。多卡机器上有时候某些卡被其他任务占用用这个参数可以避免冲突。也可以配合环境变量做显存隔离docker run --rm --gpus all \ -e NVIDIA_VISIBLE_DEVICES0,1 \ -e NVIDIA_DRIVER_CAPABILITIEScompute,utility \ nvidia/cuda:11.0-base nvidia-smi习惯之后我每次交付 GPU 服务器都会先跑一遍docker info确认 Runtimes、再跑一次完整的 CUDA 容器验证然后才交到运维手里。这几个验证步骤直接从流程上杜绝了“装完发现 GPU 没透传”的返工。希望帮到你。本文还有配套的精品资源点击获取