资讯动态

arm64 内网 Docker 与 docker-compose 离线安装实战

发布时间:2026/10/23 15:01:49 来源:尧图企业网站定制
简介面向 arm64 架构服务器与 openEuler 环境的离线部署需求这套 Docker 与 Docker Compose 安装包针对内网、无外网或网络受限场景整理适合运维人员及需要快速落地容器环境的开发者使用。压缩包共 4 个文件约 54.41MB涵盖 Docker 18.09.9 的 tgz 离线镜像包、systemd 服务配置文件、一键安装脚本以及 docker-compose 可执行文件覆盖安装、服务注册与编排工具配置等关键环节减少逐项搜集与版本匹配成本。已有 646 人学习下载经过 openEuler 系统验证对 arm64 平台兼容性有明确参考价值。使用者可据此完成 Docker 引擎与 Compose 的离线部署并借助 service 配置与脚本化流程降低手工操作遗漏适合需要可复用离线安装方案、快速搭建容器运行环境并保留排错与二次调整空间的读者。1. 内网 arm64 机器上装 Docker先想清楚离线包到底替你省了哪几步一台 arm64 服务器被推进内网机柜交付窗口只剩 SSH外网不通yum 源也不可达。此时要装 Docker 和 docker-compose靠的不是运气而是一套能在 openEuler 上落地的离线安装包里面是 aarch64 的 docker 二进制、compose 二进制、systemd 单元、daemon.json 和一键安装脚本。它解决的是“无外网、无包管理器依赖、架构必须匹配”的三重约束适合内网交付、边缘节点、实验室 arm64 机器和需要批量复装的场景。拿到包之后别急着执行脚本先确认架构、systemd 状态和存储驱动后面按拆包、安装、compose 落地、排错逐层推进。2. 拆开离线包aarch64 二进制、systemd 单元与一键脚本怎么配合2.1 目录结构与文件职责我拿到这类离线包第一件事不是运行 install.sh而是先看目录。常见结构会按“二进制、配置、服务单元、脚本、校验文件”分开目录名可能不同但职责基本一致。下面这张表按常见路径拆分实际以你手里的包为准文件名里的版本不用纠结重点看架构和可执行权限。路径作用检查点bin/dockerdDocker 守护进程file结果应为 ARM aarch64bin/docker客户端命令与 dockerd 同版本、同架构bin/containerd容器运行时必须存在否则 dockerd 起不来bin/runc底层运行时权限 0755路径在 PATH 内bin/docker-init、bin/docker-proxy容器初始化与端口转发不要漏拷否则网络异常compose/docker-composecompose v2 二进制架构同样是 aarch64systemd/docker.servicesystemd 单元ExecStart指向/usr/bin/dockerdconfig/daemon.json守护进程配置JSON 不能有注释和尾逗号install.sh一键安装脚本看是否有备份、幂等和参数解析SHA256SUMS校验清单解压后先跑校验别省这一步先用find把文件清单和大小列出来确认没有 0 字节文件也确认没有把 x86_64 的二进制混进来。命令不复杂但能提前暴露很多“装完才翻车”的问题。find docker-offline-arm64 -maxdepth 3 -type f -printf %p %s\n | sort这段命令只做一件事按路径排序列出文件大小。-maxdepth 3防止目录太深刷屏-printf比ls -l更适合看字节数。若某个二进制只有几百字节大概率是占位文件或软链不要直接 install 到/usr/bin。2.2 为什么静态二进制比离线 rpm 更省事在 openEuler 上离线 rpm 不是不能用而是依赖闭包要先解决docker 相关包、containerd、runc、iptables、libcgroup、systemd 依赖任何一个版本对不上安装器就会在目标机上停住。静态二进制把依赖压进文件本身脚本只负责拷贝、赋权、写 systemd 单元、启动服务。对交付窗口很窄的内网机器这条路更直接也更容易回滚保留旧二进制和旧daemon.json出问题能退回去。但静态二进制不是万能后悔药。它不替你加载内核模块不替你改sysctl不替你处理 firewalld 与 nftables 的边界也不包含业务镜像。常见做法是脚本只做“安装 Docker 运行时”内核参数、防火墙策略、镜像导入分别用独立步骤验收。这样出问题时能定位到是哪一层二进制没跑起来、systemd 没拉起来、网络没通、还是镜像没导入。docker-compose 也是同样逻辑v2 是 Go 静态二进制离线包里直接放一个可执行文件即可v1 依赖 Python 包在 arm64 离线环境里反而容易卡在依赖上。选型时优先docker compose插件方式命令统一脚本里少写一套兼容分支。2.3 执行前的四项检查一键脚本最怕在错误前提上执行。架构、权限、systemd、磁盘这四项先过一遍能省掉大量排查时间。下面这段检查可以直接抄到终端里跑也可以作为 install.sh 的前置逻辑。#!/usr/bin/env bash set -euo pipefail ARCH$(uname -m) case $ARCH in aarch64|arm64) ;; *) echo 需要 arm64/aarch64当前为 $ARCH 2; exit 1 ;; esac [ $(id -u) -eq 0 ] || { echo 请用 root 或 sudo 执行 2; exit 1; } command -v systemctl /dev/null || { echo systemd 不可用 2; exit 1; } DF_AVAIL$(df -Pm /var/lib | awk NR2 {print $4}) [ $DF_AVAIL -ge 2048 ] || { echo /var/lib 可用空间不足 2GB 2; exit 1; } echo 架构$ARCH 空间${DF_AVAIL}MB 检查通过set -euo pipefail让脚本在变量未定义、管道失败时立即退出避免“前面报错后面继续跑”。uname -m在 arm64 机器上可能是aarch64或arm64两个都放行。id -u判断 root是因为后面要写/usr/bin、/etc/systemd/system。df -Pm用 MB 为单位阈值 2GB 只是起步线实际还要看镜像层大小。command -v systemctl确认不是 chroot 或裁剪系统。注意如果目标机是容器内的“伪系统”systemd 可能不可用这套脚本不要硬跑。先确认systemctl is-system-running有返回再继续。2.4 一键脚本的幂等设计一键脚本要能重复执行不能第一次成功、第二次把配置覆盖坏。关键动作是备份旧配置、停止旧服务、拷贝二进制、重载 systemd、启动并检查状态。下面是一段常见骨架重点看顺序和容错不要照抄文件名。#!/usr/bin/env bash set -euo pipefail ROOT_DIR$(cd $(dirname $0) pwd) BACKUP_DIR/etc/docker/backup-$(date %Y%m%d%H%M%S) # 旧服务存在就先停不存在也不让脚本退出 if systemctl list-unit-files | grep -q ^docker.service; then systemctl stop docker || true fi # 备份旧配置避免覆盖后无法回退 mkdir -p $BACKUP_DIR [ -f /etc/docker/daemon.json ] cp -a /etc/docker/daemon.json $BACKUP_DIR/ || true # 拷贝二进制并赋权 install -d -m 0755 /usr/bin for f in dockerd docker containerd containerd-shim-runc-v2 ctr runc docker-init docker-proxy; do [ -f $ROOT_DIR/bin/$f ] install -m 0755 $ROOT_DIR/bin/$f /usr/bin/$f done # 写配置和 systemd 单元 install -d -m 0755 /etc/docker /etc/systemd/system install -m 0644 $ROOT_DIR/config/daemon.json /etc/docker/daemon.json install -m 0644 $ROOT_DIR/systemd/docker.service /etc/systemd/system/docker.service systemctl daemon-reload systemctl enable --now docker systemctl --no-pager --full status docker | sed -n 1,20pROOT_DIR用脚本所在目录避免依赖当前工作目录。systemctl stop docker || true处理“旧服务不存在”或“停止失败但可继续”的情况。cp -a保留权限和时间戳回滚时直接拷回。install -m 0755比cp多一步权限控制适合二进制。循环里用[ -f ... ]判断文件存在避免某个可选组件缺失导致整个脚本退出。最后systemctl enable --now docker同时设置开机自启和立即启动status只打印前 20 行方便看主状态。提示脚本里不要写systemctl start docker sleep 2 docker ps这种“睡两秒就当成功”的判断。改成systemctl is-active --quiet docker或直接看docker info返回值失败时把journalctl -u docker -n 80 --no-pager打出来。3. 在 openEuler 上跑一键安装从解压校验到 docker info 通过3.1 解压、校验与放置路径离线包先放到/opt或/usr/local/src不要放在/tmp里跑完就丢。解压后先校验再执行脚本。校验文件可能是SHA256SUMS也可能按文件分开没有校验文件时至少用file看架构用tar -tzf看包内路径有没有多一层目录。sudo mkdir -p /opt/docker-offline sudo tar -xzf docker-offline-arm64.tar.gz -C /opt/docker-offline cd /opt/docker-offline/docker-offline-arm64 # 有校验文件就跑没有就跳过这一行 sha256sum -c SHA256SUMS # 看关键二进制架构避免 exec format error file bin/dockerd bin/docker compose/docker-composetar -xzf的-C指定解压目录避免污染当前目录。sha256sum -c会逐行比对清单输出OK或FAILED失败就别继续。file的输出里应出现ARM aarch64或ARM64如果看到x86-64说明包拿错了后面所有步骤都不用做。解压后目录多一层是常见事cd到真正包含install.sh的那一层再执行。3.2 脚本参数与执行顺序不同包的一键脚本参数不一样常见会支持--with-compose、--data-root、--user、--no-start这类开关。先看--help没有 help 就直接打开脚本看顶部变量。不要在不清楚参数的情况下直接sudo ./install.sh尤其是它会覆盖/etc/docker/daemon.json的时候。cd /opt/docker-offline/docker-offline-arm64 # 先看脚本接受哪些参数 sudo ./install.sh --help || sed -n 1,120p install.sh # 常见执行方式安装 compose 插件数据目录保持默认 sudo ./install.sh --with-compose --data-root /var/lib/docker # 如果脚本没有参数解析按脚本内变量改完再执行 sudo bash -x ./install.sh--with-compose表示把 compose 二进制安装到 CLI 插件目录--data-root改 Docker 数据目录默认/var/lib/docker够用就不要乱改。bash -x会打印每条命令适合第一次在测试机排错生产交付时不要长期开着输出太多反而干扰。执行顺序上先停旧 docker再拷二进制再写配置再daemon-reload最后enable --now顺序颠倒会出现“新二进制配旧 unit”的怪状态。如果脚本执行到systemctl start docker报错不要重复跑脚本。先看systemctl status docker和journalctl -u docker -n 100 --no-pager常见是daemon.json语法错、dockerd路径不对、containerd没拷进去。修正后重新systemctl daemon-reload再启动比反复执行 install.sh 更干净。3.3 安装后验证版本、架构、cgroup 与存储驱动安装完成不等于可用。至少验证四件事客户端与服务端版本、架构、cgroup driver、存储驱动。openEuler 上常见期望是Cgroup Driver: systemd、Storage Driver: overlay2、Architecture: aarch64。如果 cgroup driver 是cgroupfs后面接容器编排或系统服务时容易出兼容问题。docker version docker info --format Arch{{.Architecture}} Driver{{.Driver}} Cgroup{{.CgroupDriver}} Root{{.DockerRootDir}} systemctl is-active docker systemctl is-enabled docker journalctl -u docker -n 50 --no-pagerdocker version同时看 Client 和 ServerServer 段没出来说明守护进程没起。docker info --format用 Go 模板直接取字段比翻长输出快。systemctl is-active返回active才算服务在跑is-enabled返回enabled才算开机自启。journalctl看最近 50 行重点看failed to start daemon、failed to load listeners、permission denied这类关键词。注意离线环境不要用docker run hello-world做首次验证它会尝试拉取镜像网络不通时看起来像 Docker 坏了。用包内自带的测试镜像或者只跑docker info和docker images。3.4 非 root 使用与开机自启的边界默认只有 root 能访问/var/run/docker.sock。日常用非 root 账号常见做法是加docker组然后重新登录或newgrp docker。这一步是便利性配置不是必须项生产机上谁进 docker 组等于给了很高的宿主权限别随手把所有人都加进去。# 创建 docker 组安装脚本通常会做 sudo groupadd -f docker # 把当前用户加入组 sudo usermod -aG docker $USER # 当前 shell 立即生效或者退出重新登录 newgrp docker id docker psgroupadd -f表示组已存在也不报错。usermod -aG的-a很重要漏掉会把用户从其他附加组里踢出去。newgrp docker只对当前终端生效新开窗口不一定继承所以交付时要说明“重新登录”。id看输出里有没有docker组docker ps能列出空表也算通。不要用chmod 777 /var/run/docker.sock解决权限这等于把 root 能力开放给所有本地用户。开机自启用systemctl enable docker但要注意数据目录挂载顺序。如果/var/lib/docker在独立磁盘上而 docker.service 在网络和本地文件系统之前启动可能出现目录未挂载就启动的情况。常见做法是在 unit 里加Afterlocal-fs.target或者把数据目录放到根分区。这个边界不处理重启后容器全丢的案例并不少见。4. docker-compose 离线落地插件路径、镜像导入与 pull_policy 配置4.1 compose v2 插件与独立二进制的选型docker-compose 在离线环境里有两个常见形态v2 的 CLI 插件docker compose以及独立二进制docker-compose。v2 是 Go 静态二进制不依赖 Python 包放在 arm64 离线包里最省事v1 的 Python 依赖链在无外网机器上很容易卡住。选插件方式的好处是命令统一脚本里写docker compose选独立二进制的好处是旧脚本不用改直接调docker-compose。我的建议是优先插件方式同时保留独立二进制做兼容但不要让两个版本同时抢 PATH。插件路径通常在/usr/local/lib/docker/cli-plugins/docker-compose或~/.docker/cli-plugins/docker-compose文件名必须是docker-composeDocker CLI 靠这个名字发现插件。独立二进制放/usr/local/bin/docker-compose权限 0755。两条路选一条作为主路径另一条只在迁移期存在验收时明确用哪条命令。4.2 安装到 cli-plugins 并验证插件方式的安装动作很轻建目录、拷文件、赋权、跑版本。注意目录权限/usr/local/lib/docker/cli-plugins一般 root 可写普通用户只读用户级插件目录则是~/.docker/cli-plugins适合单用户场景。# 系统级插件目录 sudo install -d -m 0755 /usr/local/lib/docker/cli-plugins sudo install -m 0755 compose/docker-compose /usr/local/lib/docker/cli-plugins/docker-compose # 验证插件是否被 docker CLI 发现 docker compose version # 如果还要兼容旧脚本再装独立二进制 sudo install -m 0755 compose/docker-compose /usr/local/bin/docker-compose docker-compose versioninstall -d -m 0755建目录并设权限install -m 0755拷文件并设可执行。docker compose version输出里应看到 v2 版本信息如果报docker: compose is not a docker command说明插件目录不对或文件名不对。独立二进制的docker-compose version用于旧脚本兼容但不要在同一个脚本里混用docker compose和docker-compose否则排错时很难判断到底调了哪个二进制。提示用command -v docker-compose和docker compose version分别确认路径与插件状态。两个都装时脚本里固定写死一种调用方式不要把选择权留给运行环境。4.3 离线镜像导入与 compose 启动compose 项目能不能起来不取决于 compose 二进制本身而取决于镜像有没有提前导入。离线环境先docker load再确认镜像架构是 arm64最后用pull_policy: never或--pull never阻止 compose 尝试联网。# 导入离线镜像包可能是一个或多个 tar docker load -i images/app-arm64.tar docker load -i images/redis-arm64.tar # 看镜像列表和架构 docker images --format table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}} docker image inspect demo/app:arm64 --format {{.Architecture}}docker load -i从 tar 包恢复镜像层和元数据。docker images用表格格式看仓库、标签、ID、大小。docker image inspect取Architecture字段必须是arm64如果显示amd64说明镜像包拿错了compose 起来也会报exec format error。镜像名和标签要和 compose 文件里的image完全一致差一个 tag 就会触发拉取。services: app: image: demo/app:arm64 pull_policy: never ports: - 8080:8080 environment: APP_ENV: prodpull_policy: never告诉 compose 不要尝试拉取直接用本地镜像。这个字段在较新的 compose 规范里可用如果现场版本不认就在命令上加--pull never。ports把容器端口映射到宿主离线环境也要检查防火墙是否放行。environment按项目实际改不要照抄。docker compose -f compose.yaml up -d --pull never docker compose -f compose.yaml ps docker compose -f compose.yaml logs --tail50up -d后台启动--pull never是命令级兜底和 yaml 里的pull_policy形成双保险。ps看容器状态和端口logs --tail50看启动日志。若容器反复重启先看日志里的镜像架构、入口命令、配置文件路径不要一上来就怀疑 Docker 本身。4.4 版本共存与回滚插件和独立二进制共存时最容易出现“终端 A 能用、终端 B 不能用”。原因是 PATH 不同、用户级插件目录不同、或者旧docker-compose还在/usr/bin。验收时用绝对路径查一遍交付脚本里固定调用方式能减少这类玄学问题。场景推荐调用检查命令新项目、脚本统一docker composedocker compose version旧脚本兼容docker-composecommand -v docker-compose单用户安装用户级插件目录ls ~/.docker/cli-plugins系统级安装/usr/local/lib/docker/cli-pluginsls -l看权限回滚时保留旧二进制和旧 compose 文件不要直接覆盖。升级前把/usr/local/bin/docker-compose或插件文件改名备份出问题改回来再hash -r清 shell 缓存。Docker 本身的回滚同理保留/usr/bin/dockerd旧文件、/etc/docker/daemon.json备份、/etc/systemd/system/docker.service备份。离线交付的底气不是“不会坏”而是坏了能在十分钟内退回去。5. 避坑与排查五个让脚本装完却跑不起来的细节5.1 现象执行 dockerd 报 exec format error现象很直接systemctl start docker失败journalctl里出现exec format error或者手动执行/usr/bin/dockerd --version直接报格式错误。原因通常不是权限而是二进制架构不匹配包是 x86_64 的机器是 aarch64或者反过来脚本把bin/下某个占位文件拷进去了。先别重装用file和readelf看机器码。file看整体类型readelf -h看Machine字段。aarch64机器上应看到AArch64不是Advanced Micro Devices X86-64。uname -m file /usr/bin/dockerd readelf -h /usr/bin/dockerd | grep -E Class|Machineuname -m确认宿主架构file确认文件架构readelf确认 ELF 头。解决方式是从离线包里重新拷正确的 aarch64 二进制别用chmod x硬修架构不对加执行权限也没用。脚本里加一道file bin/dockerd | grep -q aarch64的前置检查能提前拦住这类问题。5.2 现象systemctl start docker 失败日志指向 daemon.json现象是服务起不来systemctl status docker显示failedjournalctl -u docker里提示unable to configure the Docker daemon with file /etc/docker/daemon.json。原因多是 JSON 语法错尾逗号、单引号、注释、字段拼写错误或者把log-opts写成了字符串而不是对象。先用jq empty做语法校验再用dockerd --validate或前台调试看具体字段。jq不在离线环境里时用python3 -m json.tool也能看。前台运行会占用终端适合测试机不要在生产窗口长期挂着。jq empty /etc/docker/daemon.json sudo dockerd --config-file /etc/docker/daemon.json --debugjq empty只解析不输出返回 0 说明 JSON 结构合法。dockerd --debug前台启动能看到配置加载到哪一步失败。修完配置后systemctl daemon-reload不是必须的但systemctl restart docker必须做。若配置里改了>sysctl net.ipv4.ip_forward sysctl net.bridge.bridge-nf-call-iptables lsmod | grep -E br_netfilter|overlay firewall-cmd --list-allip_forward应为 1bridge-nf-call-iptables应为 1br_netfilter和overlay模块应加载。firewall-cmd --list-all看当前 zone 放行了哪些端口和服务。解决方式是按现场安全策略放行端口或把docker0放进信任区域不要直接systemctl stop firewalld了事交付后会被安全审计追着跑。修改sysctl后要写进/etc/sysctl.d/否则重启失效。注意br_netfilter没加载时sysctl net.bridge.bridge-nf-call-iptables可能直接报错。先modprobe br_netfilter再写/etc/modules-load.d/docker.conf重启后才会自动加载。5.4 现象compose up 卡在拉取镜像现象是docker compose up停在Pulling最后超时。原因不是 compose 坏了而是本地没有对应镜像或者镜像 tag 与 yaml 不一致compose 按默认策略尝试联网。离线环境必须显式禁止拉取。docker images --format {{.Repository}}:{{.Tag}} docker compose config | grep -n image: docker compose up -d --pull never先看本地镜像列表再核对 compose 文件里的image行。docker compose config会渲染最终配置能看出变量替换后到底是什么镜像名。--pull never是命令级兜底yaml 里加pull_policy: never是配置级兜底。两个都加现场不会因为版本差异退化成联网拉取。若镜像名对但架构不对up可能不报拉取错误而是启动后exec format error这时回到 5.1 检查镜像架构。5.5 现象非 root 用户 permission denied现象是普通用户执行docker ps报permission denied while trying to connect to the Docker daemon socket。原因是用户不在docker组或者加了组但当前 shell 没重新加载组信息。还有一种情况是/var/run/docker.sock权限被改坏。id getent group docker ls -l /var/run/docker.sock sudo usermod -aG docker $USER newgrp dockerid看当前用户附加组getent group docker看组成员ls -l看 socket 属主和权限。usermod -aG后必须重新登录或newgrp否则当前进程的组 ID 不变。不要用chmod 777修 socket这会把 Docker 守护进程的控制面开放给所有本地用户。生产环境更稳妥的做法是只给交付账号加组或者用 sudo 白名单限制具体命令。6. 验收与复装把离线安装压成三条可重复的命令6.1 三项验收离线安装做完不要只看“脚本没报错”。我通常压成三条命令架构、Docker 服务信息、compose 版本。三条都过才把机器交出去。检查项命令通过标准架构uname -maarch64或arm64Docker 服务docker info --format {{.Architecture}} {{.Driver}} {{.CgroupDriver}}aarch64 overlay2 systemdcomposedocker compose version有 v2 版本输出uname -m docker info --format {{.Architecture}} {{.Driver}} {{.CgroupDriver}} docker compose version systemctl is-active dockerdocker info这条同时看架构、存储驱动、cgroup driver比docker version更直接。systemctl is-active补一刀服务状态。任何一项不符合先回到对应章节查不要靠重启碰运气。6.2 一个交付习惯血泪经验是离线机器上最容易出问题的不是安装脚本而是“装完没留证据”。后来我每次交付都强制走一遍uname -m docker info docker compose version再把journalctl -u docker -n 200 --no-pager存到交付记录里。下次同一批机器复装直接对比上次输出架构、驱动、cgroup 哪一项变了一眼就能看出来。这套 arm64 离线包的价值不在脚本多花哨而在你把检查顺序固定下来换一台 openEuler 机器也能按同样节奏复现。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑