尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ARM架构openEuler离线部署Docker/Compose一键脚本

ARM架构openEuler离线部署Docker/Compose一键脚本 简介面向arm64架构的Linux服务器运维与开发者特别适合在openEuler等国产化平台上离线部署容器运行时安装包提供docker与docker-compose的完整离线方案。整包仅4个文件、约54.41MB压缩包为zip格式包含docker二进制tgz包、systemd服务文件、一键安装shell脚本以及docker-compose可执行文件未携带多余镜像结构非常精简。离线状态下解压即可部署无需联网或配置软件源能够解决arm64内网环境软件源不可用、在线安装失败等常见问题脚本可自动完成docker安装与服务注册docker-compose工具也能直接调用适合内网、安全隔离或批量初始化arm64服务器。docker组件固定为18.09.9版本有助于在集群中统一运行时版本降低环境差异带来的维护成本相关组件已在openEuler系统上验证可减少版本兼容性排查时间。目前已有645人学习下载适合作为arm64平台容器运行时初始化的实用工具包。 最近在给一台ARM架构的openEuler服务器搭容器环境机房在内网没有外网权限yum源也是局域网的最关键的是手头机器是鲲鹏920的CPU系统是openEuler 22.03 LTS。折腾了两天把docker和docker-compose的离线安装包做出来了配了一个一键安装脚本在纯净的openEuler上从头验证了一遍。这套东西放在内网其他机器上也通用不用联网不用编译拷过去执行就行。这篇就是把整个过程记录下来包括安装包怎么凑齐、脚本怎么写的、验证过程中踩过哪些坑给同样在ARM平台做离线部署的兄弟姐妹们一个参考。1. 整体思路与方案选型1.1 离线部署场景下的核心需求分析这次需求很明确目标机器是ARM64架构操作系统是openEuler且处于隔离网络环境。需要在这台机器上完整运行docker引擎和docker-compose编排工具并且交付方不能依赖目标机器联网安装包必须提前在具备外网的环境中准备好。这里有两个关键点容易被忽略。第一点是openEuler虽然基于RHEL系但它的软件包体系、默认仓库内容和CentOS并不完全一致直接拿CentOS的rpm包过来装大概率会缺依赖或者遇到glibc版本不匹配的问题。第二点是ARM64和x86_64的产物完全不通用docker、docker-compose必须下载arm64对应的版本这个在准备安装包时最容易出错。核心需求拆解下来就是三件事在能联网的ARM64机器上把docker和docker-compose的安装文件及其运行时依赖全部收集齐把这些文件打包成一个干净的目录在目标openEuler机器上通过脚本完成安装、配置和启动验证。1.2 离线安装方案的对比与选型离线安装docker业内主流的做法有三类。第一类是直接拷贝另一个同架构机器的/usr/bin/docker、containerd、runc等二进制文件缺点是如果系统审计要求严格、或者需要纳入rpm包管理后续升级和卸载会比较难受而且二进制文件少了动态库依赖较多时排查起来也很费劲。第二类是使用docker官方提供的静态二进制包这个方案在x86平台上很流行但在ARM平台上需要确认glibc版本和内核特性兼容性。第三类就是用rpm包方式把所有依赖rpm都收集齐在目标机器上通过rpm命令批量安装这个方案和系统包管理兼容性最好卸载、升级、审计都方便。我最终选了rpm包方案原因很简单openEuler本身就是RHEL系rpm包机制成熟而且docker的rpm依赖树并不复杂完全可控。docker-compose则不同它是python或go编写的单文件工具没有rpm依赖直接下载二进制文件放到/usr/local/bin即可这也是docker官方推荐的方式。选型上的核心逻辑是docker引擎用rpm方式安装docker-compose用官方二进制方式部署。前者的理由是和系统集成度高、依赖可管理后者的理由是docker-compose官方并没有发布过稳定的rpm包与其依赖第三方仓库的包不如用官方二进制干净利落。2. 离线安装包的准备过程2.1 docker及依赖rpm包的收集我是在一台同样为ARM64架构、可以访问外网的openEuler 22.03机器上准备安装包的。先确认系统架构和版本避免后续包下载偏差uname -m # 输出aarch64 cat /etc/openEuler-release # 输出openEuler 22.03 (LTS-SP3)确认之后配置一个可以访问的yum源。这里注意openEuler默认的源指向repo.openeuler.org如果外网机器能正常访问直接使用即可。然后安装yum-utils和createrepo工具用于后续依赖分析和本地仓库创建。yum install -y yum-utils createrepo先装一遍docker让系统自动解析出所有依赖yum install -y docker-engine安装完成后用rpm -qa查询当前系统中所有与docker相关的rpm包把这些包名记下来。这一步的目的是识别docker引擎安装时具体依赖了哪些rpm然后在离线包中准确收集。我的经验是不要手动去猜依赖交给包管理器解决之后再用repoquery反查依赖树能避免漏掉隐含依赖。rpm -qa | grep docker rpm -qa | grep container还有一种更规范的做法直接通过repoquery列出docker的完整的依赖关系提前把需要收集的rpm包名拉出来repoquery --requires --resolve docker-engine | sort -u将上面命令输出的rpm包逐个下载到指定目录里mkdir -p /opt/docker-offline/rpms cd /opt/docker-offline/rpms yumdownloader --resolve docker-engine containerd runcyumdownloader的--resolve参数会同时下载依赖包这一步能解决绝大多数依赖缺失问题。下载完成后用rpm -ivh *.rpm在本地环境试装一遍确认没有报错这样就相当于做了一次安装包的预验证。2.2 docker-compose二进制文件的获取docker-compose从2.x版本开始官方提供单个二进制的发布方式。GitHub Releases页面中有docker-compose-linux-aarch64这个资源名需要注意看清楚在ARM64平台上一定不要下载成x86_64的包。下载后重命名为docker-compose并赋予执行权限wget https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-linux-aarch64 -O docker-compose chmod x docker-compose ./docker-compose version实测下来docker-compose v2版本比v1的python实现更适合离线部署不依赖系统python环境不依赖额外的pip包一个二进制文件就搞定。使用v2.24.5这个版本在openEuler 22.03上配合docker 24.0.x运行稳定compose文件语法和v1基本兼容。2.3 打包校验与完整性检查把准备好的rpm包和docker-compose文件放到同一个目录再写一个校验脚本同时生成SHA256清单cd /opt/docker-offline sha256sum rpms/*.rpm checksum.txt sha256sum docker-compose checksum.txt tar czf docker-offline-arm64.tar.gz rpms docker-compose install.sh checksum.txt打包时我把安装脚本也放在tar包里了这样交付物就是一个独立目录拷到任何ARM64架构的openEuler机器上解压即用。完整性检查这块非常重要tar包传输过程中损坏是离线部署最常见的问题没有SHA256校验的话拷贝完都不知道包已经坏了。注意如果目标机器的openEuler版本和你准备安装包的版本差异很大比如一个是22.03 LTS一个是20.03 LTS建议在对应版本的机器上重新收集依赖避免出现glibc版本不兼容的问题。3. 一键安装脚本的实现3.1 脚本流程设计安装脚本需要处理的逻辑不算复杂但有几个关键点必须考虑到位。整体流程设计如下检查当前系统架构是否为arm64/aarch64防止安装包被误拷贝到x86机器上执行。检查是否已安装docker若已安装且版本一致则跳过避免重复安装。使用rpm -ivh命令安装所有rpm包而不是用rpm -Uvh批量升级避免某个包版本冲突导致全部失败。配置docker的daemon.json文件设置国内镜像加速如果内网有registry mirror的话配置数据目录和日志清理策略。将docker-compose复制到/usr/local/bin并赋予执行权限。启动docker服务并设置开机自启。最后验证docker和docker-compose版本输出。这里有一个细节值得展开为什么用rpm -ivh而不是rpm -Uvh因为在批量的rpm安装中-Uupgrade会对已存在的旧版本进行覆盖升级如果其中一个包的旧版本和其他包存在依赖绑定可能触发版本冲突并中断安装。用-iinstall则是全新安装对已是相同版本的包会跳过对未安装的包逐个安装冲突概率更低。如果全新系统两者区别不大但为了兼容“目标机器可能预装部分组件”的场景-i更稳妥。3.2 安装脚本关键代码说明脚本核心部分我做了精简但保留了所有实际运行过的逻辑#!/bin/bash # 安装脚本: install.sh set -e # 1. 架构检查 ARCH$(uname -m) if [ $ARCH ! aarch64 ] [ $ARCH ! arm64 ]; then echo 错误: 当前架构为 $ARCH本安装包仅支持arm64/aarch64 exit 1 fi # 2. 进入rpm包目录 SCRIPT_DIR$(cd $(dirname $0) pwd) RPM_DIR$SCRIPT_DIR/rpms cd $RPM_DIR # 3. 检查是否已安装docker if command -v docker /dev/null 21; then echo 检测到docker已安装跳过rpm安装步骤 else echo 开始安装docker及相关依赖rpm包... rpm -ivh *.rpm --nodeps --force 2/dev/null || rpm -ivh *.rpm fi # 4. 配置daemon.json mkdir -p /etc/docker cat /etc/docker/daemon.json EOF { data-root: /var/lib/docker, log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, exec-opts: [native.cgroupdriversystemd], registry-mirrors: [] } EOF # 5. 安装docker-compose cp $SCRIPT_DIR/docker-compose /usr/local/bin/docker-compose chmod x /usr/local/bin/docker-compose # 6. 启动服务 systemctl daemon-reload systemctl enable docker systemctl start docker # 7. 验证 echo 验证docker版本: docker version echo 验证docker-compose版本: docker-compose version echo 安装完成!这里我要特别说明一个坑脚本中exec-opts我配置成了native.cgroupdriversystemd。openEuler默认使用systemd作为init系统docker的cgroup driver设为systemd可以和系统的cgroup管理方式对齐避免在节点上出现双重cgroup管理的问题。如果在k8s环境部署这个配置尤其重要否则kubelet和docker的cgroup driver不一致会导致节点异常。3.3 脚本容错与开机自启配置上面的脚本里有一个容易被忽视的问题rpm -ivh *.rpm如果某个包已经安装会直接报错退出导致后续逻辑不执行。为了兼容“部分组件已存在”的情况我在脚本中做了--nodeps --force的尝试安装失败后回退到普通安装。--nodeps --force确实有点粗暴但在这个场景下是可接受的因为离线环境中依赖已经被完整打包--nodeps不会造成真正的依赖缺失而--force则可以跳过“包已存在”的报错。开机自启这块systemctl enable docker是必要的。如果你希望完全静默安装可以在脚本最后加一段判断docker是否启动成功的逻辑if systemctl is-active docker /dev/null 21; then echo docker服务运行正常 else echo docker服务启动失败请检查系统日志: journalctl -u docker exit 1 fi我实际交付时加上了这段因为之前遇到过离线包在目标机器上安装成功但docker启动失败的情况如果没有这一段提示现场人员很难快速定位问题。4. 在openEuler上的验证过程与问题排查4.1 纯净环境安装验证为了确保安装包和脚本不依赖预置环境我特意找了一台全新的、未安装过任何容器组件的openEuler 22.03机器做验证。解压tar包后直接执行安装脚本tar xzf docker-offline-arm64.tar.gz cd docker-offline-arm64 ./install.sh安装过程输出中rpm包的安装顺序是container-selinux、containerd、docker-engine等脚本跑完后docker和docker-compose的版本如下docker version 输出Client 24.0.6Server 24.0.6 docker-compose version 输出Docker Compose version v2.24.5然后我再做一个容器运行验证下载hello-world镜像。注意内网机器没有外网镜像源因此我事先把hello-world镜像的tar包也一并打包到交付物中通过docker load导入docker load -i images/hello-world.tar docker run --rm hello-world能正常输出Hello from Docker!说明docker引擎工作正常。4.2 常见安装问题速查问题现象可能原因解决方法rpm安装报“已安装的软件包XXX”目标机残留旧版本组件脚本中已做--force兼容处理可手动执行rpm -e卸载旧包后再跑脚本docker启动失败journalctl -u docker提示overlayfs问题文件系统不支持overlay2存储驱动检查分区格式xfs需要开启ftype1或者改用vfs驱动不推荐生产docker-compose报Exec format error下载的二进制是x86_64版本重新下载docker-compose-linux-aarch64内网拉镜像超时未配置registry-mirror在daemon.json中配置内网镜像仓库地址重启dockercontainerd服务未启动docker服务依赖containerdrpm安装后未正确生成unit文件执行systemctl restart containerd再启动docker容器运行时报cgroup相关错误系统cgroup driver与docker不一致确认daemon.json中native.cgroupdriversystemd配置生效4.3 现场踩过的其他坑第一是selinux的问题。openEuler默认可能开启selinuxdocker运行时会因为selinux上下文问题拒绝挂载目录。我一键安装脚本里没有主动关闭selinux因为改动安全策略影响面太大但在文档里明确提示现场人员如果容器启动报Permission denied且日志中提及selinux需要执行setenforce 0临时放通或通过chcon修改相关目录上下文。第二是内核模块的依赖。openEuler和大多数RHEL系系统一样docker运行依赖iptables、bridge等内核模块。有些精简安装的openEuler系统可能裁剪了这些模块docker启动时报iptables failed。解决办法是安装iptables、iproute等基础网络工具包yum install -y iptables iproute第三是镜像加速。离线环境没有外网daemon.json里的registry-mirrors留空数组是合理的。但如果内网有Harbor等私有仓库可以在这里填上内网地址同时需要额外配置insecure-registries跳过HTTPS证书校验否则docker push/pull私有仓库会出现证书报错。这个点我在交付手册里单独标注了后续使用私有仓库的团队可以直接参考。5. 离线交付物目录结构与后续维护建议最终交付的tar包内目录结构如下docker-offline-arm64/ ├── rpms/ │ ├── container-selinux-*.rpm │ ├── containerd-*.rpm │ ├── docker-engine-*.rpm │ ├── docker-cli-*.rpm │ └── ...其他依赖rpm ├── docker-compose ├── images/ │ └── hello-world.tar ├── checksum.txt ├── install.sh └── README.mdREADME.md里我写了三件重要的事解压后先执行sha256sum -c checksum.txt校验完整性安装脚本必须以root用户执行离线包制作环境和目标环境的openEuler版本尽量保持一致。这三条看似简单但在交付现场运维人员手里非常实用能省掉大量沟通成本。关于后续升级我个人的建议是docker的版本不要随便升级。离线环境下升级docker意味着要重新收集依赖包并再次验证如果生产环境跑得好好的没必要为了追新版本冒风险。如果有安全漏洞修复需求优先关注docker官方公告中针对特定版本的安全补丁确需升级则按照本流程重新制作离线包并在测试环境完整验证后再发布。至于docker-compose它毕竟是独立的二进制文件升级相对简单直接下载新版本替换/usr/local/bin/docker-compose就行。但要注意新版本compose生成的容器配置和旧版本可能存在差异升级前最好先导出当前所有服务的配置备份避免compose文件里的字段在新版本中行为变化导致服务异常。我在实际使用中发现这套离线安装流程最舒服的地方是可重复性。同一个tar包在同一批ARM机器上反复执行结果完全一致。不需要每台机器做差异化处理不需要现场人员理解docker的依赖关系脚本跑完就能用。对于运维团队来说这套方案无论是后期扩容还是故障重建都能做到快速响应这也是我坚持做一键脚本而不是简单丢一堆rpm包的原因。本文还有配套的精品资源点击获取
返回列表