ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

天翼云OS内网离线安装Docker-CE保姆级教程:依赖包与本地仓库实操

天翼云OS内网离线安装Docker-CE保姆级教程:依赖包与本地仓库实操 天翼云OSctyunos的内网环境我接触得比较多前阵子刚帮一个客户在内网机器上部署Docker-CE环境是标准的隔离内网没有外网权限yum 源也是断的。折腾了两天踩了不少坑从依赖包收集、本地仓库搭建到 Docker 启动失败排错一轮下来算是把离线安装的完整链路摸清了。这篇文章就按“保姆级”标准给你过一遍思路、命令、依赖清单、坑位都给你列出来照着走基本不会卡壳尤其适合下面几类人在政务云、企业内网、私有机房做基础环境交付的运维和交付工程师需要在 ctyunos 或同源 CentOS 系系统上离线部署 Docker 环境的实施人员自己接触不到公网 yum 源、但又被分派了“把 Docker 给我装上”任务的小伙伴先说好这篇不是纯理论是我实际部署中的操作记录和改进版本每一条命令我都尽量解释为什么这么干出现报错该怎么查。依赖包清单放在第 3 节可以直接抄。1. 核心思路离线安装不是“拷一个rpm就行”1.1 先把 ctyunos 和 Docker-CE 的“血缘关系”搞清楚ctyunos 是天翼云基于开源 Linux 发行版定制的服务器操作系统官网描述里也会提到它兼容主流 CentOS 生态。这意味着绝大多数 CentOS 的二进制 rpm 包在 ctyunos 上可以直接安装Docker-CE 也不例外。但要注意“兼容”不等于“完全一致”我在实际部署中遇到过 ctyunos 自带的内核版本较老、某些模块未加载的问题好在 Docker-CE 对内核的要求并不高3.10 以上即可ctyunos 默认内核能满足。在开始之前建议先执行这几条命令确认系统底子cat /etc/os-release uname -r arch getenforce/etc/os-release里的 NAME 会显示为 “ctyunos” 或类似字样版本号可能是 2.0、3.0 这类。uname -r看内核版本Docker 对内核的最低要求是 3.10如果是 3.10 以下的旧内核先升级内核再考虑装 Docker否则就算装上了启动容器也会各种崩溃。getenforce用于查看 SELinux 状态后面排查问题会用得上。1.2 为什么离线安装一定要做“本地仓库”而不是 rpm -ivh 硬怼很多人第一次做离线安装会下意识找一台有网的机器把 docker-ce 的 rpm 下载下来然后到内网机器上rpm -ivh docker-ce.rpm。这个做法十有八九会失败因为 Docker-CE 依赖的包非常多比如container-selinux、containerd.io、docker-ce-cli、iptables、libcgroup、slirp4netns等用 rpm 逐个安装会陷入依赖地狱而且顺序错了就报错循环依赖更是难解。正确做法是在有外网的机器上用yumdownloader把 Docker-CE 及所有依赖包一次性拉下来然后在内网用createrepo制作一个本地 yum 仓库最后用yum install docker-ce安装。这样 yum 会自动解析依赖顺序内网机器就相当于有了一个“只包含 Docker 所需包”的迷你软件源安装过程跟在线环境几乎没有区别。这就是“离线安装也要用包管理器”的核心逻辑。1.3 两条可行的依赖包获取路线选哪条看你的条件我总结下来离线 Docker-CE 部署的依赖包来源主要有两种你可以根据现场条件选路线A有网跳板机 yumdownloader 全量拉取这是最稳妥的办法。找一台能访问外网、且系统版本与内网机器一致或高度相似的机器配置好 BaseOS、Extras、EPEL 等 yum 源然后用yumdownloader直接解析全部依赖并下载到指定目录。再把整个目录打包拷贝到内网。路线B有网机器直接安装后打包在跳板机上用yum install docker-ce正常安装好 Docker然后通过rpm -qa | grep -E docker|containerd|container-selinux把相关包挑出来再用rpm -ivh逐个拷贝到内网。这条路线的问题在于你很难精确判断 Docker 实际依赖了哪些包漏掉一个就白跑一趟。实际项目中我优先推荐路线A流程干净、全量、可复现。后面的操作全部按路线A来展开。2. 环境准备与版本选型2.1 确认 ctyunos 的版本类型和 Docker 版本兼容性ctyunos 有多个版本系列不同系列对应的 rpm 基础架构不同。我这里以 2.0/3.0 这种基于 CentOS 7/8 的版本为例进行说明。一个关键判断方法是看/etc/redhat-release或者rpm -q centos-release如果里面带有 “el7” 或者 “el8” 的特征就可以直接选对应版本的 Docker-CE 仓库。Docker-CE 官方为 CentOS/RHEL 系提供的仓库地址是https://download.docker.com/linux/centos/version/x86_64/stable/其中version是 7 或 8。利用这个仓库配合yumdownloader就能下载到匹配系统版本的 Docker-CE 及依赖包。Docker 版本的选择上如果不是为了搭配 K8s 等容器编排平台直接上最新稳定版问题不大。但如果你的内网环境以后要装 Kubernetes建议选择 K8s 官方支持列表内的版本例如 1.24 之前使用 dockerd 作为运行时的情况并且安装后要锁定版本防止 yum update 自动升级导致 K8s 组件版本不匹配。2.2 离线包制作机器的“系统一致性”原则这是一个特别容易翻车的细节在跳板机上下载依赖包时源机器的系统版本、架构必须与目标内网机器一致。举个例子你的内网 ctyunos 是 x86_64 架构、基于 CentOS 7 的版本那么跳板机也应是同架构、同大版本的系统。如果跳板机是 CentOS 8下载到的 rpm 大多是 el8 包拿到 CentOS 7 系的 ctyunos 上安装必然报错requires libc.so.6(GLIBC_2.28)(64bit)或el8 package is for a different operating system。这类问题在离线环境里特别难查因为报错信息不会直接说“你的包版本不对”。所以在开始下载前一定要用uname -m确认架构、用cat /etc/os-release确认系统版本二者和目标机器保持一致才继续。2.3 跳板机上需要预先安装的工具在跳板机上下载依赖包最核心的工具是yum-utils和createrepo。yum-utils提供yumdownloader命令createrepo用于生成本地仓库元数据。两个工具都通过 yum 安装即可yum install -y yum-utils createrepo如果跳板机之前没有配置过 EPEL 仓库建议先装上 EPEL因为部分 Docker 依赖尤其是container-selinux在默认源里可能没有EPEL 里通常能找到yum install -y epel-release安装完成后先执行yum makecache fast刷新缓存确保仓库可用再进入下一步。3. 离线依赖包获取与本地仓库搭建这一节是整个离线部署的精髓也是最费时间的部分。我会把每一步操作、参数、验证方法都写清楚。3.1 用 yumdownloader 全量拉取 Docker-CE 及依赖包首先要配置 Docker 官方源。在跳板机上新建一个仓库文件/etc/yum.repos.d/docker-ce.repo写入以下内容以 CentOS 7 为例[docker-ce-stable] nameDocker CE Stable - $basearch baseurlhttps://download.docker.com/linux/centos/7/$basearch/stable enabled1 gpgcheck1 gpgkeyhttps://download.docker.com/linux/centos/gpg然后刷新缓存并尝试下载全部依赖包yum makecache fast mkdir -p /opt/docker-rpm yumdownloader --resolve --destdir/opt/docker-rpm docker-ce docker-ce-cli containerd.io这里要重点解释--resolve参数的作用。如果没有这个参数yumdownloader只会下载你指定的那几个主包并不会自动解析依赖。加了--resolve后它会像yum install一样解析所有依赖关系并把所有需要的 rpm 全部下载到--destdir指定的目录。命令跑完后查看目录内容确认包含以下关键包不同版本号略有差异ls /opt/docker-rpm/我的实际使用稿里核心包大致有这些包名作用备注docker-ceDocker 主程序包必装docker-ce-cliDocker 命令行工具与主程序分离必装containerd.io容器运行时被 Docker 调用必装docker-ce-rootless-extrasRootless 模式支持组件推荐一起安装container-selinuxSELinux 策略模块允许容器使用 SELinux最容易缺的依赖fuse-overlayfsRootless 模式使用的存储驱动如果不用 rootless 可不装slirp4netnsRootless 网络支持如果不用 rootless 可不装iptables防火墙规则管理工具Docker 网络依赖 iptables 规则iptables-libsiptables 运行库Docker 网络依赖nftablesnftables 规则管理工具新版 iptables 的空表兼容libcgroup控制组管理工具部分环境会作为依赖被拉取policycoreutils-python-utilsSELinux 管理工具container-selinux 的依赖注意yumdownloader --resolve下载的依赖包列表以 yum 实际解析结果为准不同系统版本、不同 Docker 版本会有差异。上面这个表是最核心的包不是最终全部列表。现场以/opt/docker-rpm目录里实际下载到的 rpm 文件为准。下载完成后用tar把整个目录打包便于拷贝到内网cd /opt tar czvf docker-rpm.tar.gz docker-rpm/3.2 依赖包清单的“核心包”逐一说明很多人在离线部署时抱怨“怎么缺了那么多依赖”其实是没搞清楚 Docker-CE 的依赖链逻辑。我把最容易缺的包单独拎出来讲container-selinux这个包我认为是离线安装的第一大坑。它默认可能在跳板机的基础 yum 源里找不到需要启用 EPEL 或者 Extras 仓库才能下载。如果缺失安装 docker-ce 时会直接报Error: Package: docker-ce-xxx.el7.x86_64 (docker-ce-stable) Requires: container-selinux 2.107解决办法是在跳板机上确保epel-release已安装并且yumdownloader解析时能拉到这个包。如果手动补充可以直接在http://mirror.centos.org/centos/7/extras/x86_64/Packages/或 EPEL 对应路径里下载对应版本的 rpm再放进依赖包目录。containerd.io从 Docker 19.03 开始containerd 从 Docker 主程序里拆了出来作为独立组件维护。当你安装 docker-ce 时yum 会自动解析并下载 containerd.io所以不用刻意手动指定但要在--resolve后的结果里确认它存在。iptables 相关Docker 依赖 iptables 来管理容器网络实现端口映射、网桥转发、NAT 等功能。虽然系统可能已经装了 iptables但版本差异可能导致 Docker 报错所以在依赖目录里看到 iptables 的 rpm 是很正常的。3.3 在目标内网机器上制作本地 yum 仓库内网机器上先建一个目录把拷贝过来的 rpm 包解压放进去然后执行createrepo生成仓库元数据cd /opt/docker-rpm createrepo .执行完成后目录下会生成一个repodata子目录这就是本地 yum 仓库的“索引”。接下来新建一个仓库文件例如/etc/yum.repos.d/docker-local.repo[docker-local] nameDocker Local Repository baseurlfile:///opt/docker-rpm enabled1 gpgcheck0注意这里的gpgcheck0因为本地仓库里的 rpm 签名验证没有太大意义且离线环境下若缺少 GPG 公钥反而会导致安装失败。如果希望保留验证则需要把 GPG key 也一并导入但对于内网环境我建议关闭。为了不影响系统原有源只保留这个本地仓库建议先把系统自带的.repo文件临时改名或移走比如mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/这样yum在解析时只会看到我们创建的本地仓库避免因为网络不可达而等待超时。然后执行yum clean all yum makecache当看到docker-local仓库的元数据被加载就说明仓库已经生效。可以用下面的命令验证yum repolist yum list docker-ce --showduplicates4. 内网离线安装 Docker-CE 全过程4.1 校验依赖完整性正式安装前先做一次“试安装”检查这一招能提前避开 90% 的依赖问题。使用yum install的--assumeno或-y的相反模式模拟安装看会不会报依赖缺失yum install --assumeno docker-ce docker-ce-cli containerd.io如果输出里出现Requires: xxx的错误说明依赖包没下载全回到跳板机用yumdownloader --resolve补下对应包然后重新createrepo。这一条真的很重要离线环境最怕的就是装上装下发现缺一个包来回拷贝浪费时间。确认无缺失后正式执行安装yum install -y docker-ce docker-ce-cli containerd.io安装过程应当是一路畅顺的结束后用rpm -qa | grep docker验证安装结果正常能看到docker-ce、docker-ce-cli等包已安装。4.2 配置 /etc/docker/daemon.json内网部署关键安装完成后先别急着启动。先配置/etc/docker/daemon.json这是在内网环境里最容易忽略的一步。纯内网环境没有公网 Docker Hub 访问能力所以不要配公网镜像加速器比如 Docker 官方或各云厂商的加速地址否则后面docker pull还是会超时。正确做法是在 daemon.json 里配置内网 Harbor/Registry 地址或者干脆不配 registry-mirrors直接使用私有仓库拉取。一个实用的基础配置如下{ exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, storage-driver: overlay2, registry-mirrors: [https://your-registry.example.com], insecure-registries: [your-registry.example.com:5000] }下面逐个解释这些参数的意义exec-opts设置 cgroup 驱动为 systemd。在现代 Linux 发行版中systemd 是主流的 init 系统而且如果后面要对接 K8s 之类的容器编排工具cgroup driver 必须统一为 systemd否则会报failed to parse kubelet cgroup之类的错误。log-driver和log-opts控制容器日志大小防止容器日志无限增长打爆磁盘。这个在长期运行时特别重要JVM 类应用、Nginx 这类访问日志多、输出量大的容器如果不限制日志大小很容易一夜之间就把/var/lib/docker/containers目录填满。我建议max-size设在 50m 到 100mmax-file设 2~3 个兼顾排查和磁盘空间。storage-driver设置为overlay2配合现代内核性能与稳定性都优于旧的devicemapper。registry-mirrors这里写你的内网仓库地址如果是纯离线环境没有仓库可以忽略。insecure-registries如果你搭建的是 HTTP 协议的私有仓库必须加这一段否则 docker pull 会因证书问题拒绝连接。配置完成后执行systemctl daemon-reload。4.3 启动 Docker 并验证核心功能启动命令很简单systemctl daemon-reload systemctl enable --now docker systemctl status docker看到active (running)后先跑两个基础命令确认 Docker 工作正常docker info docker ps -adocker info的输出里重点检查这几项Storage Driver: overlay2Cgroup Driver: systemdKernel Version与系统uname -r一致Server Version是刚刚安装的 Docker 版本如果Cgroup Driver显示的是cgroupfs而不是systemd说明 /etc/docker/daemon.json 可能没生效需要确认文件格式是合法的 JSON然后重启 Dockersystemctl restart docker再验证网络。内网环境没有外网但可以创建一个测试容器并连接到内网网关验证容器网络是否正常docker run -it --rm alpine sh如果本地没有 alpine 镜像、也没有内网镜像仓库这一步会卡在 pull 阶段。建议在跳板机上提前docker pull alpine或docker pull nginx然后docker save -o alpine.tar alpine打包再拷贝到内网docker load -i alpine.tar。这里的做法我在第 5 节还会提到。最后确认开机自启systemctl is-enabled docker如果显示enabled则说明 Docker 服务已设置开机自动启动。这一步在服务器重启后尤为重要很多现场交付后第二天发现容器没启动原因就是忘了 enable。5. 常见问题与排查技巧实录5.1 安装时报 “Requires: container-selinux 2.107”这是我遇到的最频繁的问题也是离线安装 Docker-CE 的第一大坑。报错原因就是依赖包目录里没有container-selinux。解决方案分两种情况如果还没有打包去内网直接回到跳板机安装 EPEL 源后再拉取yum install -y epel-release yumdownloader --resolve --destdir/opt/docker-rpm container-selinux如果已经带着打包目录进了内网发现缺包可以通过其他途径拿到container-selinux的 rpm拷入/opt/docker-rpm然后重新执行createrepo .。需要注意的是container-selinux的版本必须满足报错里的最小版本要求比如要求 2.107你不能拿一个2.77的老包去凑数否则 yum 会一直报同一个错误。5.2 Docker 启动失败journalctl 里报 iptables / nftables 冲突新版 CentOS/RHEL 8 系列默认使用 nftables 作为防火墙后端而 Docker 传统上依赖 iptables。如果 Docker 启动日志里出现类似Failed to start Docker Application Container Engine iptables failed: iptables --wait -t nat -A DOCKER...一般有两种处理方式一种是让 Docker 继续使用 iptables需要把系统防火墙规则切换到iptables-nft的兼容层。很多系统会提供iptables-nft和iptables-legacy两个版本检查并切换update-alternatives --config iptables选择iptables-nft这一项。多数情况下将iptables指向nft兼容版本Docker 就能正常工作。另一种方式是检查 firewalld 是否开启了nftables后端。如果你不需要系统防火墙直接停掉 firewalldsystemctl stop firewalld systemctl disable firewalld在纯内网且网络环境可控的场景下关闭 firewalld 是很多运维的选择但这要根据你所在机构的安全规范来不要随意动手。5.3 安装了 docker-ce 但docker命令不存在这个坑乍一看很莫名其妙其实是因为新版 Docker-CE 将 CLI 和守护进程分离成了两个包docker-ce和docker-ce-cli。如果你只安装了docker-ce那么只有dockerd守护进程没有/usr/bin/docker命令。解决方法很简单yum install -y docker-ce-cli这个包早在下载依赖的时候就应该被yumdownloader --resolve解析进来如果你确认下载目录里有但内网机器没装执行上面的命令补上即可。5.4 内网拉不到镜像容器跑不起来这是纯离线环境下最容易遇到、且最容易被低估的问题。以为装好 Docker 就万事大吉结果docker run hello-world就卡在 pull 上。我的通用做法是在跳板机上把所有需要离线交付的镜像先docker pull好然后打 tar 包拷入内网后用docker load导入。# 跳板机有网环境 docker pull nginx:1.24 docker pull redis:7.0 docker pull mysql:8.0 docker save -o images.tar nginx:1.24 redis:7.0 mysql:8.0 # 内网环境 docker load -i images.tar docker images有一点要注意docker save后tar 包里的镜像不包含latest标签如果要打latest标签在开 tag 时就要明确指定或者在 load 之后手动docker tag。另外如果镜像很多很大建议用gzip压缩后再拷贝docker save nginx:1.24 | gzip nginx.tar.gz5.5 内网离线安装 docker-compose 的补充参考标题里提到了离线安装 docker-compose我再补充几句。Docker Compose V2 是通过docker compose一条二进制集成的插件不一定需要单独离线安装。如果是 V1docker-compose单文件获取方式很简单在有网的机器上下载docker-compose-linux-x86_64二进制拷贝到内网后改名放到/usr/local/bin/docker-compose加上执行权限chmod x /usr/local/bin/docker-compose docker-compose version5.6 其他常见问题速查现象原因排查/处理方法yum install卡在等待网络系统源未禁用内网无法访问公网将/etc/yum.repos.d/下多余源移走只保留本地仓库docker pull超时没正确配置内网私有仓库或加速器检查 daemon.json 中的 registry-mirrors 与 insecure-registries容器启动后端口映射失败防火墙规则或 Docker 网络模式问题临时停用 firewalld 测试排查 iptables 规则docker info中 Storage Driver 不是 overlay2内核模块未加载或 daemon.json 未生效执行modprobe overlay、modprobe br_netfilter重启 Docker系统重启后 Docker 未启动忘记 enable 服务执行systemctl enable docker6. 从项目中沉淀的几个操作习惯这次离线部署之后我养成了几个固定习惯写出来供你参考。第一所有离线软件包在交付前一定要写版本清单和校验值。下载完成后用sha256sum生成校验文件和 rpm 包一起交付既能防止传输过程损坏也方便后期定位版本问题。cd /opt/docker-rpm sha256sum *.rpm SHA256SUMS第二打包整个/opt/docker-rpm目录而不是只拷贝几个 rpm。因为依赖关系是链式的多拷几个包不碍事少拷一个却可能导致整个安装失败。离线安装宁可“装多不可装少”这是铁律。第三同一套离线资源要记录好“源系统版本”和“目标系统版本”。我在不同项目里发现同样是 Docker-CE 20.10 系列el7 和 el8 的 rpm 完全不能混用一旦混用光排查版本兼容性就要花大半天。建议在 rpm 目录旁边加一个README.txt写明跳板机的 OS 版本、Docker 主版本、拉取日期。第四如果内网环境同时要交付多台机器不要每台都tar解压一遍再createrepo。更好的办法是把/opt/docker-rpm目录打成 tar.gz拷到内网后解压一遍生成 repo 元数据后用 NFS、共享目录或者内部 HTTP 服务共享给其它机器让其余机器通过http://或file://方式指向同一个仓库批量安装效率高一个数量级。最后再分享一个我自己的小技巧yumdownloader下载过程中如果出现某个包多次拉取失败不要反复重试先yum makecache fast刷新元数据再看仓库配置是否正确很多时候是仓库 URL 变了或者 GPG key 缺失导致拉包被拒绝。离线安装 Docker 本身不复杂真正麻烦的是依赖收集和启动排障。把本文第 3 节的依赖包清单准备齐全再按第 4 节的步骤走内网环境下基本一次就能过。真遇到问题也别慌按照第 5 节的路子逐条排查大多数坑都在表里了。
返回列表