资讯详情

openEuler arm64 离线部署 Docker 与 Compose

📅 2026/10/23 20:56:16 | 华诺云谱 👁 阅读
openEuler arm64 离线部署 Docker 与 Compose
简介面向 arm64 架构服务器与信创环境运维人员的 Docker 离线部署包聚焦无外网、内网受限场景下的容器环境搭建已在 openEuler 系统下完成验证适合需要快速补齐 Docker 与 Docker Compose 基础运行环境的中初级运维及开发人员。压缩包共 4 个文件包含 Docker 二进制压缩包、systemd 服务配置、一键安装脚本以及 Docker Compose 可执行文件整体约 54.41MB体积精简便于通过内网传输后直接部署。目前已有 646 人学习下载具备一定的实践参考价值。资源价值在于将离线安装所需的核心组件与脚本集中打包减少分别搜集二进制包、服务配置和编排工具的重复工作并降低版本不匹配风险同时保留清晰的文件分类方便读者理解 Docker 离线部署的组成结构并为后续容器编排、服务管理与环境排错提供可复用的基础材料。1. 离线装 Dockerarm64 的包别拿 x86 那份顶上有个场景我见过不止一次内网机器是 arm64 的手里只有一份 x86_64 的 docker 离线包心想二进制嘛解压赋权跑起来就行结果systemctl start docker之后journalctl -u docker里只有一行exec format error。在 openEuler 的 arm64 环境里装 docker 和 docker-compose第一道坎从来不是命令写错而是包和机器对不上。这台机器往往没有外网、没有 yum 源、连curl都出不去装坏了也没有后悔药只能靠提前把版本、架构、依赖盘清楚。下面这套流程是我在断网 arm64 机器上反复走过的那一遍。2. 装前盘底openEuler 上先确认这五件事离线安装最怕的是装到一半才发现缺东西而这时候既没有源也没有网。所以我在解压任何压缩包之前会先花十分钟把这台机器的底摸清楚架构、系统分支、内核 cgroup 模式、iptables 实现、SELinux 状态、磁盘余量。这几项里任何一项判断错后面 daemon.json 就会写错服务起不来还得回头重来。这一章的命令全部是只读的不改系统任何配置跑完心里就有数了。2.1 架构与系统版本aarch64 和 x86_64 不能混第一步永远是确认架构。别看机器外壳也别信同事口头说的直接敲命令# 确认 CPU 架构aarch64 才是这套 arm64 包能落地的机器 uname -m # 期望输出 aarch64 # 有些系统会显示 arm64两种写法都算对但绝不是 x86_64 uname -auname -m输出aarch64说明你手上这份 arm64 包用得上如果是x86_64后面所有步骤都不用看了包拿错了。这里有个容易忽略的点同一个压缩包里如果混进了 x86 的runc或docker-proxydockerd主进程能起来但一跑容器就报exec format error排查起来很绕。所以解包之后我还会单独对每个二进制做一次架构核对这个放到第 3 章讲。接着看系统分支# openEuler 的版本信息在 VERSION_ID 里别只看 PRETTY_NAME cat /etc/os-release # 单独确认发行版标识避免拿 CentOS 的包直接套 grep -E ^(ID|VERSION_ID) /etc/os-releaseopenEuler 的不同 LTS 分支之间内核版本和 systemd 版本差别不小直接影响两件事cgroup 是 v1 还是 v2以及 systemd 单元文件里能不能用某些指令。我一般会把这两条也一起记下来# systemd 版本决定 unit 文件里 Delegate、TasksMax 这些能不能用 systemctl --version | head -n 1 # 内核版本决定 overlay2 和 cgroup v2 的支持程度 uname -r把这三行输出记在记事本上后面写 unit 文件和 daemon.json 时随时对照。离线环境里没有回头路这些信息就是你的地图。2.2 内核与 cgroup决定后面 daemon.json 怎么写cgroup 版本是 arm64 离线装 docker 时最容易被跳过、又最容易翻车的一项。判断方法很简单# 查看 cgroup 挂载类型 stat -fc %T /sys/fs/cgroup # 输出 cgroup2fs 表示 cgroup v2unified 模式 # 输出 tmpfs 表示 cgroup v1 或混合模式如果是cgroup2fs说明系统跑在 cgroup v2 上那么 docker 的 cgroup driver 必须跟 systemd 保持一致否则容器里的 CPU、内存限制会失效甚至起不来。这就是后面 daemon.json 里exec-opts要写native.cgroupdriversystemd的原因。老一些的 docker 版本对 cgroup v2 支持不完整如果包里的版本偏旧可能需要在启动参数上加内核开关这个我会在第 5 章的排查里展开。再确认一下 cgroup 控制器有没有挂上# 看 cpu、memory 控制器是否可用缺了容器资源限制就是摆设 cat /sys/fs/cgroup/cgroup.controllers 2/dev/null || \ ls /sys/fs/cgroup/cpu /sys/fs/cgroup/memory 2/dev/null输出里有cpu memory pids这类字样就算正常。如果这里就是空的先别装 docker去查内核启动参数是不是加了cgroup_disablememory之类的东西那是更底层的问题。2.3 依赖与防火墙、SELinux 的现状静态二进制方式装 docker 的好处是不依赖 yum 源坏处是系统级依赖得自己补。我会用一条循环把常见的几项过一遍# 逐个检查离线安装会用到的系统组件缺哪个补哪个 for p in tar gzip xz iptables iproute systemd libcgroup; do if rpm -q $p /dev/null 21; then echo OK $p else echo MISSING $p fi donetar、gzip、xz是解包用的iptables关系到容器网络能不能通iproute提供ip命令排查网桥问题离不开libcgroup在部分分支上影响 cgroup 挂载。出现MISSING的去系统 ISO 的 Packages 目录里找对应 rpm用rpm -ivh补装别硬扛着装 docker装完也是带病运行。然后是防火墙和 SELinux 的现状这两项只查不改改不改等看完再说# 防火墙状态firewalld 运行时会和 docker 抢 iptables 规则 systemctl is-active firewalld # SELinux 状态enforcing 模式下静态二进制装的 docker 很容易被拦 getenforcefirewalld是active的话docker 启动时会自己插 NAT 规则两边都在管 iptables规则顺序容易乱表现为容器能起、但宿主机访问不通。我的习惯是安装阶段先systemctl stop firewalld systemctl disable firewalld等 docker 跑通、网络验证完再按实际安全要求把端口策略补回去。getenforce如果是Enforcing静态二进制方式没有配套的 SELinux 策略包dockerd大概率起不来这个也留到排查章细说。2.4 磁盘与目录/var/lib/docker 放哪最后一项是磁盘。docker 的镜像、容器层、日志全在># 看根分区和 /var 的余量镜像一多几十 G 很快就没了 df -h / /var /var/lib 2/dev/null如果/var没有独立分区而机器上又挂了一块大盘常见做法是在安装前就把目录规划好比如把大盘挂到/data然后 daemon.json 里把># overlay2 对底层文件系统有要求xfs 需要 ftype1 findmnt -no FSTYPE / xfs_info / 2/dev/null | grep -i ftype如果根分区是 xfs且ftype0那 overlay2 存储驱动用不了只能退回vfs性能和磁盘占用都会明显变差。这种情况要么重做文件系统要么接受vfs在第 4 章配置存储驱动时会用到这个结论。3. 解包落地用静态二进制把 docker 和 docker-compose 装到位盘底做完进入真正的安装环节。离线包走的是静态二进制路线不经过包管理器所以每一步落在哪个目录、权限给多少都得自己定。这一章按“看包、备份、解包、装二进制、注册服务、装 compose”的顺序推进中间任何一步失败都能停下来回退不会把系统搞成半装状态。3.1 解开压缩包先看目录结构拿到压缩包的第一件事不是解压到系统目录而是先看里面有什么# 只列出内容不解压确认包结构和架构 tar -tzf docker-arm64-版本.tgz | head -n 30正常结构大概是这样.tgz里套一个docker/目录下面是全套二进制docker/ ├── containerd ├── containerd-shim-runc-v2 ├── ctr ├── docker ├── docker-init ├── docker-proxy ├── dockerd └── runcdockerd是守护进程docker是客户端containerd和containerd-shim-runc-v2是容器运行时runc负责真正拉起进程docker-proxy处理端口映射。这套二进制是自包含的互相之间的路径依赖靠PATH解决所以必须全部放进同一个目录。解压到一个临时目录逐个核对架构# 解到临时目录不碰系统路径 mkdir -p /tmp/docker-pkg tar -xzf docker-arm64-版本.tgz -C /tmp/docker-pkg # 逐个文件确认是 aarch64防止包里混进 x86 二进制 for f in /tmp/docker-pkg/docker/*; do printf %-45s %s\n $(basename $f) $(file -b $f | cut -c1-60) done每个文件都应该出现ARM aarch64字样。只要有一个显示x86-64这个包就不能用别想着“其他都是对的凑合一下”那个错的二进制一定会在某个时刻被调用到。3.2 二进制落到 /usr/bin 与 systemd 单元确认无误后开始正式安装。第一步永远是备份同名文件离线机器上装坏了没有源可以重装# 备份可能被覆盖的同名二进制时间戳目录方便回滚 ts$(date %Y%m%d%H%M%S) bak/root/docker-bak/$ts mkdir -p $bak for f in docker dockerd containerd ctr runc docker-proxy docker-init containerd-shim-runc-v2; do [ -e /usr/bin/$f ] cp -a /usr/bin/$f $bak/ done echo 备份目录$bak然后拷贝并给权限# install 一步到位完成拷贝和赋权避免 chmod 漏文件 install -m 0755 /tmp/docker-pkg/docker/* /usr/bin/ # 验证客户端能执行此时守护进程还没起能出版本号就说明二进制本身没问题 docker --version dockerd --versioninstall -m 0755比cp加chmod稳妥它保证每个文件都是可执行的。docker --version在这里能打出版本号说明动态库依赖齐全如果报not found或者GLIBC版本错误那就是系统基础库太旧这套包不匹配得换更早编译的版本。接着写 systemd 单元。静态安装没有docker.service得自己放一份# /etc/systemd/system/docker.service [Unit] DescriptionDocker Application Container Engine Afternetwork-online.target firewalld.service Wantsnetwork-online.target [Service] Typenotify ExecStart/usr/bin/dockerd ExecReload/bin/kill -s HUP $MAINPID TimeoutStartSec0 Restartalways RestartSec2 LimitNOFILEinfinity LimitNPROCinfinity LimitCOREinfinity TasksMaxinfinity Delegateyes KillModeprocess OOMScoreAdjust-500 [Install] WantedBymulti-user.target几个参数值得说清楚。Typenotify表示dockerd启动完成后会主动通知 systemd配错了会表现为systemctl start一直卡住直到超时。Delegateyes让 docker 自己管理 cgroup 子树cgroup v2 环境下不加这个容器资源限制会全部失效。LimitNOFILEinfinity是因为容器多的时候文件句柄消耗很快默认值根本不够。Restartalways配合RestartSec2是保底dockerd偶发崩溃能自己拉起来。写完执行重载和启动# 重载 unit 并设为开机自启再启动 systemctl daemon-reload systemctl enable docker.service systemctl start docker.service # 立刻看状态不要等 systemctl status docker.service --no-pager3.3 docker-compose 的两个位置独立二进制还是 CLI 插件docker-compose 在 arm64 上同样要拿对应架构的二进制。它有两种落法区别在于调用方式是docker-compose还是docker compose。第一种当独立命令行工具用# 放到 /usr/local/bin再软链到 /usr/bin 保证 PATH 里能找到 install -m 0755 docker-compose-linux-aarch64 /usr/local/bin/docker-compose ln -sf /usr/local/bin/docker-compose /usr/bin/docker-compose # 验证 docker-compose version第二种作为 docker CLI 插件# docker CLI 会自动扫描这两个插件目录 mkdir -p /usr/local/lib/docker/cli-plugins install -m 0755 docker-compose-linux-aarch64 /usr/local/lib/docker/cli-plugins/docker-compose # 插件方式的调用语法是 docker compose中间是空格 docker compose version两种方式可以并存但不建议出问题时很难判断到底调的哪一份。我的取舍是新环境统一用插件方式脚本里统一写docker compose如果存量脚本里全是docker-compose那就装独立二进制省得改一堆文件。要提醒一句compose 的 v1 和 v2 在version:字段、depends_on条件写法上有差异离线包里给的是哪一版就在脚本里按哪一版的语法写别混着抄。3.4 一键脚本逐段读能改的地方在哪包里带的安装脚本能省事但离线环境我从来不闭眼执行先读一遍重点看它有没有架构校验、有没有备份、失败会不会回滚。一个合格的脚本开头通常是这样的#!/usr/bin/env bash set -euo pipefail # 架构自检不是 aarch64 直接退出别往下装 ARCH$(uname -m) if [ $ARCH ! aarch64 ]; then echo 当前架构 $ARCH 与安装包不匹配已退出 exit 1 fi # 权限自检整个流程要写 /usr/bin 和 /etc/systemd if [ $(id -u) -ne 0 ]; then echo 请用 root 或 sudo 执行 exit 1 fiset -euo pipefail这三项很关键-e遇错即停-u用到未定义变量就报错pipefail让管道里任一环节失败都算失败。没有这三行的脚本中途某步失败了可能继续往下跑最后装出个四不像。我一般会在这个基础上加两个自己的开关一个是--data-root把数据目录指到大盘一个是--skip-compose只装 docker 不装 compose。改的时候注意脚本里的路径要和前面 3.2、3.3 保持一致尤其是二进制来源目录和 systemd 单元路径。执行前先bash -n install.sh做语法检查再bash -x install.sh走一遍看执行轨迹确认每一步落在哪比直接跑完再排查省事得多。4. 配置 daemon.json改对这几个参数少返工一半二进制装完、服务能起来只是“装上了”离“能用”还有一段。daemon.json 决定了数据放哪、日志怎么转、cgroup 怎么接、网络怎么建这些参数在离线环境里改一次要重启一次服务所以最好一次写对。这一章给的是一份可以直接抄的配置以及每个参数为什么这么取。4.1># 写入 /etc/docker/daemon.jsonJSON 不允许注释别把 shell 注释抄进文件 mkdir -p /etc/docker cat /etc/docker/daemon.json EOF { data-root: /data/docker, log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, exec-opts: [native.cgroupdriversystemd], storage-driver: overlay2, iptables: true, live-restore: true, default-address-pools: [ { base: 172.31.0.0/16, size: 24 } ] } EOF># 1. 先做语法校验JSON 写错的报错信息很模糊 python3 -m json.tool /etc/docker/daemon.json /dev/null echo JSON OK # 2. 重载配置并重启 systemctl daemon-reload systemctl restart docker.service # 3. 确认新配置真的生效别只看服务是 active docker info | grep -E Docker Root Dir|Storage Driver|Cgroup Driver|Logging Driver输出里Docker Root Dir应该是新设的路径Cgroup Driver应该是systemdStorage Driver是overlay2。这三行对不上说明配置文件没被读到常见原因是文件放在了/etc/docker/daemon.json之外的路径或者启动参数里用--config-file指了别处。还有一个细节如果># 服务状态、启动时间、有没有反复重启 systemctl status docker.service --no-pager systemctl show docker.service -p NRestarts -p ActiveEnterTimestamp # 核心进程是否都在dockerd 会拉起 containerd ps -ef | grep -E dockerd|containerd | grep -v grepNRestarts如果不是 0说明服务在反复重启别急着往下走先看日志。containerd没起来的话容器一定跑不了。第二层客户端层确认配置生效、组件能对话# 守护进程和客户端版本、API 版本是否匹配 docker version # 关键配置是否按预期生效这一条比什么都直接 docker info | grep -E Server Version|Storage Driver|Cgroup Driver|Docker Root Dir|Live Restore # compose 是否可用 docker compose version || docker-compose versionServer Version有输出说明客户端能连上守护进程Cgroup Driver是systemd、Storage Driver是overlay2、Docker Root Dir是你设的路径三行对上配置这一关就过了。第三层运行时层才是真正的验货。没有外网就导入本地镜像# 从离线包里导入一个基础镜像tar 文件跟着安装包一起带过来的 docker load -i /opt/images/base-arm64.tar docker images # 跑一个短生命周期的容器验证 runc 和命名空间都正常 docker run --rm base-arm64:local /bin/sh -c echo runtime-ok; uname -m输出里有runtime-ok和aarch64说明从镜像层、运行时到内核这条链路是通的。这一步过了比看十遍systemctl status都踏实。6.2 用两个本地镜像做一次 compose up单容器跑通还不够compose 的网络编排是另一个层面的东西。写一个最小的两服务编排用刚才导入的本地镜像# /opt/verify/docker-compose.yml services: app: image: base-arm64:local command: [/bin/sh, -c, while true; do echo app-alive; sleep 30; done] networks: - verify-net probe: image: base-arm64:local command: [/bin/sh, -c, sleep 5; getent hosts app || ping -c 1 app] depends_on: - app networks: - verify-net networks: verify-net: driver: bridgeprobe服务的作用是验证 DNS 解析和容器间网络它能通过服务名app解析到对方说明自定义桥接网络建起来了docker 内置的 DNS 也在工作。# 起服务观察两个容器是否都正常 cd /opt/verify docker compose up -d # 看 probe 的日志里面应该有 app 的解析结果 docker compose logs probe # 收尾别把验证容器留在生产机上 docker compose down docker network ls | grep verify-net最后那条docker network ls应该查不到verify-net说明down把网络也清干净了。如果网络残留后面再建同名网络会冲突这是个容易被忽略的收尾动作。从那以后我每次在 arm64 上装完 docker 和 docker-compose都强制走一遍这三层验证尤其是docker info里那三行和一次完整的compose up再down不跑完不敢说这台机器装好了。离线环境的坑大多不是装的时候暴露而是几天后业务上线的某个时刻才炸出来那时候再回头查成本高得多。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑