尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

ARM架构下Harbor离线安装避坑指南

发布时间:2026/9/29 19:26:31

资讯中心
01
ARTICLE

ARM架构下Harbor离线安装避坑指南

ARM架构下Harbor离线安装避坑指南
简介面向ARM64架构的Harbor 2.8.2离线安装包专为无外网或内网受限场景设计帮助运维人员在鲲鹏、飞腾等ARM平台快速搭建企业级容器镜像仓库。压缩包共6个文件主要包括shell安装脚本、Harbor主服务离线tar.gz镜像包、YAML配置模板并附带license授权文件与prepare预检工具整体约639.65MB。其中sh脚本负责安装启动tmpl模板可定制harbor.ymlprepare用于环境检查覆盖离线部署关键步骤。已有260人学习下载适合具备基础Docker经验、需为企业内网或边缘机房搭建私有镜像仓库的开发运维人员。通过这份离线包可在无外网环境初始化Harbor完成镜像上传、权限分配及复制策略配置并利用镜像扫描、漏洞检测等内置功能保障供应链安全尤其适配ARM服务器承载的边缘计算与物联网业务。1. 拿到 arm64 的 Harbor 离线包先弄清这个 tar.gz 解决什么问题在 ARM 机器上搭 Harbor 私有仓库最大的成本不是 Harbor 本身而是找到一个和 CPU 架构对得上的离线安装包。很多人在官网下载页看到harbor-offline-installer这个名字就顺手点了 x86_64 版本结果在鲲鹏、飞腾或者树莓派上跑install.sh容器全部起不来日志里清一色exec format error。标题里这个harbor-offline-installer-v2.8.2-arm64.tar.gz就是给 arm64 环境准备的 v2.8.2 离线安装包Harbor 的镜像、部署脚本、配置模板全部打进一个 tar.gz目标机器不需要连外网也能完成部署。这篇笔记适合需要在国产化服务器麒麟 V10 这类、ARM 服务器或边缘节点上自建容器镜像仓库的运维和开发人员从环境检查、安装、验证一路讲到排错和后续维护。2. ARM 架构下部署 Harborarm64 与 x64 的选型差异和环境体检Harbor 官方离线安装包按 CPU 架构分开发布。harbor-offline-installer-v2.8.2-arm64.tar.gz对应 arm64 平台文件里的容器镜像都带linux/arm64平台信息x86_64 版本带的是linux/amd64。选型阶段最不能省的就是确认目标机器的架构否则离线包遇到的所有问题都会以“容器起不来”的症状呈现排查成本远高于下载一个正确的包。2.1 arm64 和 x64 的差别为什么一个离线包不能跨架构通用arm64 和 x64 是两套完全不同的指令集x86_64 是 CISCarm64 是 RISC。指令编码、寄存器宽度、调用约定都不一样编译出来的二进制互不兼容。容器镜像为什么也分架构是因为镜像里的可执行文件是编译后的原生二进制比如 Harbor 的 core、registry、jobservice 这些组件都是对应架构的 ELF。Docker 在 pull 镜像时通常会根据节点的uname -m去获取对应平台的镜像层但离线包里的 tar.gz 已经把平台固定死了x86 包 load 进 ARM 的 docker daemon镜像会正常出现在本地容器一启动走到入口程序加载时发现 ELF 头对不上报exec format error。有人会问我开启了 binfmt_misc是不是就能在 ARM 上跑 amd64 的容器能跑但那是用 qemu 用户态模拟做翻译执行性能损失非常大容器里每一条系统调用都要经过翻译层。Harbor 一跑就是十几个容器Portal、Jobservice、Registry 之间还有频繁的 HTTP 调用生产环境这么干等于给整套系统加了几倍延迟。所以 arm64 的机器必须用 arm64 的离线包这也是标题里带arm64的价值所在。2.2 用 3 条命令完成部署前环境体检拿到离线包先别急着解压先确认目标机器真的能跑。我会按下面三条命令做检查任何一条不通过都先解决再继续。# 1. 确认内核硬件架构。aarch64 就是 arm64x86_64 就得换包 uname -m # 2. 确认 docker daemon 所在平台的架构以及版本号 docker version --format {{.Server.Os}}/{{.Server.Arch}} docker version --format docker version: {{.Server.Version}} # 3. 确认 docker-compose 命令存在且版本大于 1.29 docker-compose version第一条输出必须是aarch64。这里有个容易混淆的地方uname -m输出aarch64docker version的Server.Arch输出arm64两者是同一平台的不同叫法看到这两个值都说明架构正确。第二条重点看 Server 不是 ClientClient 架构不对没有关系daemon 是 arm64 才能跑 arm64 的容器。第三条如果提示command not found不等于机器不能装 Harbor只是系统里只有docker composev2 插件或者干脆用的是 podman需要补装或做软链处理方法在第 4 章里展开。这里多说一句系统差异。Ubuntu 22.04 arm64 上装 docker-ce 后通常只带docker compose插件路径一般是/usr/libexec/docker/cli-plugins/docker-composeCentOS 7 上自己下二进制的话文件名通常是docker-compose-linux-aarch64麒麟 V10 的软件源里可能默认装了 podman根本没有 docker-compose。这些情况在安装 Harbor 前检查出来比执行 install.sh 后报错再处理要省事得多。2.3 数据盘与目录规划解压之前先想清楚这三件事安装前还应该想清楚数据放哪而不是解压完随便执行。第一件事是 data_volume。Harbor 的镜像、数据库、日志都放在这一个目录下生产环境一定要放到独立的数据盘系统盘只放程序。很多人默认放在/data/harbor如果你机器上有单独挂载的/data分区直接用它如果没有建议单独加一块盘挂到/data。第二件事是磁盘容量。离线包本身不大解压后加镜像大约 1GB 多一点但 Harbor 仓库的容量不是按离线包大小算的是按你要存的镜像总量算的。一个中等规模的开发团队加上镜像的层历史一年 50GB 到 200GB 很常见。我一般建议剩余空间不低于 50GB 再开始安装同时预留 10% 到 20% 给后续的 GC垃圾回收和临时文件。第三件事是运行环境。生产环境用物理机或原生 arm64 云主机不要在 qemu 模拟的 arm64 上跑原因前面已经讲了。我在某次验证环境里图省事用 qemu-system-aarch64 开了一台虚拟机装 Harbor最后 push 一个 200MB 的镜像花了 20 分钟这就是玄学排查半天后得到的血泪经验。检查项期望值不满足时的后果uname -maarch64容器起不来exec format errorServer.Archarm64同上docker version20.10Registry 与 core 的 API 兼容问题docker-compose1.29 或 v2install.sh 在依赖检查阶段退出磁盘剩余50GBload 镜像失败或存储空间不足3. 用 harbor-offline-installer-v2.8.2-arm64.tar.gz 完成离线安装这一章是从拿到 tar.gz 到 Harbor 能正常登录的完整流程。假设前面的环境检查都通过了目标机器可以完全离线。3.1 解压离线包和生成 harbor.yml必改的 4 个参数先把离线包解压进入解压目录后能看到 install.sh、common.sh、harbor.v2.8.2.tar.gz、harbor.yml.tmpl 这些文件。tar -zxvf harbor-offline-installer-v2.8.2-arm64.tar.gz cd harbor cp harbor.yml.tmpl harbor.yml ls -lhinstall.sh 是总的安装入口负责依赖检查、镜像加载、容器编排common.sh 是脚本的公共函数库依赖检查和日志输出都靠它harbor.v2.8.2.tar.gz 是真正的镜像包十几个 Harbor 组件的镜像都在里面harbor.yml.tmpl 是配置模板复制成 harbor.yml 后按需修改。接下来打开 harbor.yml有 4 个参数是我每次部署必改的hostname: harbor.internal.example.com # 必改填本机 IP 或可解析的域名 http: port: 80 harbor_admin_password: ChangeMe_2024 # 必改默认 Harbor12345 一定要换掉 data_volume: /data/harbor # 必改指到独立数据盘hostname 不只是一个展示用的名字Harbor 签发的认证 token 里带着这个地址客户端docker login和docker pull都会拿它和实际访问地址比对。如果留 localhost局域网里其他机器登录一定失败报错内容和证书、主机名不匹配有关填 IP 是最省事的做法但有域名并且打算上 HTTPS 就填域名。harbor_admin_password 是 Web 控制台和 docker login 的初始密码默认值在公网上被扫到就会被改掉建议 16 位以上。data_volume 改成独立数据盘避免后面镜像把系统盘写满。如果暂时不想配 HTTPS把https:下面两行注释掉同时保证http.port是 80 或你指定的端口。注意 Harbor 不允许 http 和 https 同时启用模板里默认两段都存在要按需删改否则 install.sh 的配置检查会直接报错退出。改完不要马上执行安装先确认数据目录存在父目录权限正常。提示harbor_admin_password 改完记得存到密码管理器。Harbor 忘记 admin 密码后的重置流程很折腾不值得在生产环境试。3.2 执行 install.sh最小命令、耗时与输出解读配置改好后切换回离线包解压目录直接执行安装命令。cd harbor sudo ./install.sh --with-trivyinstall.sh 做的事情分四段先做依赖检查检查 docker、docker-compose 版本、磁盘剩余空间、CPU 架构然后把 harbor.v2.8.2.tar.gz 里十几个镜像 load 进 docker再根据 harbor.yml 生成 docker-compose.yml最后docker-compose up -d启动所有容器并做健康检查。--with-trivy是开启漏洞扫描插件。Trivy 扫描依赖漏洞数据库离线环境第一次扫会因为库没导入而失败所以离线部署如果不需要扫描功能可以不加这个参数要加就提前把漏洞库文件放到指定目录这个细节常见于交付文档我这里先提一句避免执行完才发现内置扫描器不可用。整个安装过程取决于磁盘速度机械盘可能要 5 到 10 分钟SSD 上一般两三分钟就能看到最后一行输出。执行成功时安装脚本最后会打印这样一行----Harbor has been installed and started successfully----。看到这一行之前终端里任何[FATAL]或[ERROR]都说明有步骤没通过不要继续往下验证。如果中途失败日志不会专门写到某个文件而是直接打到终端。排错时有两个命令最有用docker-compose ps看容器启动状态docker logs container看具体容器日志。比如 registry 这个容器名就是docker logs registry。不要反复执行 install.sh 重试先找到第一次失败的原因否则后面的镜像加载、容器编排会叠加错误。3.3 安装后的验证清单docker login 和镜像推送装完不能只看 Web 页面能打开还要把 docker login 和 push 走一遍这一步能验证网络链路、认证、仓库写入全部正常。# 登录输入密码后应显示 Login Succeeded docker login harbor.internal.example.com -u admin -p ChangeMe_2024 # 给本地镜像打上 Harbor 地址的 tag再推送 docker tag nginx:1.27-alpine harbor.internal.example.com/library/nginx:1.27 docker push harbor.internal.example.com/library/nginx:1.27如果你是 arm64 环境本地要拉一个和架构匹配的 nginx 镜像比如docker pull --platform linux/arm64 nginx:1.27-alpine否则推送上去的镜像将来在 arm64 节点也跑不了这是容易被忽略的一环。library 是 Harbor 内置的公开项目适合放公共基础镜像单位内部项目建议先在 Web 界面上建独立项目再推送避免所有人都在 library 里堆镜像。推送成功后到 Web UI 的项目页面应该能看到 nginx:1.27 这个仓库和对应 tag。这里顺便验证一件事点开仓库详情看架构标签如果显示 ARM 或 arm64说明这条链路完全正常。docker login 如果失败按第 4 章第 1 节的路子去查 hostname 和 http/https 配置八成是配置和访问地址不一致。到这里最小可用的 Harbor 已经跑起来了。接下来的第 4 章专门写我在 ARM 环境里遇到过的坑每一条都用现象、原因、解决的方式说明可以直接对照。4. 离线安装避坑在 ARM 环境翻车最多的 5 个问题这一章覆盖的 5 个问题按出现频率排序。每一条都按现象、原因、解决展开解决部分给出可复制的命令。4.1 容器报 exec format error最常见也最容易被忽略现象install.sh 执行成功但是 docker-compose ps 看到多个容器反复 Restarting或者直接退出用 docker logs registry 看到standard_init_linux.go:228: exec user process caused: exec format error。原因load 进 docker 的镜像架构和本机不一致。典型场景有两种一种是把 harbor-offline-installer 的 x86_64 版本下载到了 ARM 机器另一种是在 x86 下载机上用默认参数 docker pull 拉镜像再手动 save/load 到 ARM 机器镜像实际是 amd64 的。解决先确认到底哪个环节出了问题。# 看镜像架构输出 amd64 就说明镜像架构不对 docker image inspect goharbor/registry:2.8.2 --format {{.Architecture}} # 看主机架构 uname -m如果镜像架构是 amd64 而主机是 aarch64下载对应 arm64 的离线包重新安装如果是手动搬运的镜像重新走 docker pull --platform linux/arm64 的流程。这个坑我在 CentOS 7 上搭 Harbor 时栽过一次后来把架构检查写进了部署清单再没翻过车。4.2 install.sh 提示 docker-compose not found现象执行 install.sh 后很快退出输出提示缺少 docker-compose 或者版本低于 1.29.0。有些机器上 docker compose version 有输出但 docker-compose version 报 command not found。原因Harbor 的 install.sh 内部调用的是 docker-compose 命令也就是 compose v1 的独立二进制。现在很多新装的 Docker 只带 docker compose 这个 v2 插件命令名不一样另外麒麟 V10 这类系统上系统包管理器里可能只预装了 podman根本没有 docker-compose。解决优先做一个软链接把 compose v2 插件接到 docker-compose 命令名上。# 找到 compose 插件实际路径 find /usr/libexec /usr/lib/docker -name docker-compose 2/dev/null # 软链到 /usr/local/bin sudo ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin/docker-compose # 验证 docker-compose version如果系统里确实没有 compose 插件在能上网的机器上下载 docker-compose 的 arm64 二进制传到目标机器放到 /usr/local/bin/docker-compose然后 chmod x。这里注意两个架构有同名文件拿 amd64 的 compose 放到 arm 机器上一执行又会遇到 4.1 里的架构坑下载时认准 linux-aarch64 字样。4.3 registry 容器反复重启数据卷权限问题现象Harbor 其余容器都起来了docker-compose ps 里 registry 一直 Restarting。docker logs registry 里出现mkdir /storage: permission denied或open /storage/docker/registry: permission denied之类的输出。原因data_volume 指向的目录宿主机上属主和权限不对。Harbor 的 registry 容器不是以 root 运行的而是容器内一个 uid 为 10000 的用户。直接以 root 在宿主机 mkdir /data/harbor目录属主是 root容器内用户没有写权限。解决把整个数据卷的属主改成 10000:10000再重新拉起容器。sudo chown -R 10000:10000 /data/harbor cd /path/to/harbor docker-compose up -d这个命令在迁移数据卷、从备份恢复时也要执行一遍否则恢复后的 registry 同样起不来。另外提醒一下chown -R 对镜像目录会跑一段时间数据量大时不要中途中断否则目录属主会处于半改半不改的状态。4.4 nginx 容器起不来端口冲突与 https 段配置不干净现象docker-compose ps 里 nginx 容器反复退出docker logs nginx 看到bind: address already in use或者安装脚本的配置检查阶段报错说配置无效。原因http.port 或 https.port 对应的宿主机端口已被占用。最常见的是服务器上已经有 nginx、Apache 或者其他 Web 服务占着 80另外 harbor.yml 里如果同时保留 http 和 https 两个配置段install.sh 配置检查会认为这是非法组合因为 Harbor 默认不允许同时开两套入口。解决先把那个端口上跑着的进程找出来确认能不能让端口。sudo lsof -i :80 # 如果确认可停systemctl stop 对应服务否则改 Harbor 端口如果确认要保留原有服务把 harbor.yml 里 http.port 改成 8080把 https: 段整个注释掉重新执行 install.sh。改完之后后面所有 docker login 都要带端口比如docker login harbor.internal.example.com:8080tag 也要写成harbor.internal.example.com:8080/library/nginx:1.27。4.5 在 qemu 模拟的 arm64 环境里部署性能慢到不可用现象在 x86 宿主机上用 qemu-system-aarch64 开 ARM 虚拟机Harbor 能装上但 docker login 请求都要等几十秒push 一个 100MB 镜像耗时 10 分钟以上CPU 持续占满。原因qemu 模拟 arm64 使用的是软件翻译执行CPU 指令翻译加上内存虚拟化的开销非常大Harbor 的容器密集访问进一步放大了延迟。这不是 Harbor 配置问题是模拟环境的天然性能瓶颈。解决不要在 qemu 模拟的 arm64 环境里做 Harbor 部署尤其是作生产交付验证。找个原生 arm64 的物理机或者公有云的 arm64 实例来跑。如果只是为了验证离线包的目录结构和 install.sh 流程可以在模拟环境里快速走一遍但所有性能类结论都不要信。把这 5 个问题排查完Harbor 基本能稳定跑起来。实际交付时还有一类问题集中在镜像怎么进去也就是离线包场景把 tar.gz 转成 Harbor 里的镜像下一章专门讲。5. 离线镜像入仓把 tar.gz 里的镜像搬进 ARM 版 HarborHarbor 本身装好只是第一步仓库里必须有镜像Kubernetes 或 KubeKey 这类工具才愿意用它。离线环境没有 Docker Hub 可用所以镜像一般以 tar.gz 形式流传本章讲两种进仓方式以及和 KubeKey 对接时的注意点。5.1 用 docker pull --platform 和 save/load 搬运 arm64 镜像在能上网的下载机上先确认镜像有没有 arm64 版本再用 --platform 参数下载避免拉到 amd64 的镜像。# 在 x86_64 下载机上强行拉取 linux/arm64 的镜像 docker pull --platform linux/arm64 mysql:5.7 # 把镜像保存成 tar.gz docker save mysql:5.7 | gzip mysql-5.7-arm64.tar.gz保存出来的 tar.gz 可以拷到内网 ARM 机器或者直接推到 Harbor。到了 ARM 机器上用 docker load 解出来打上 Harbor 前缀再 push。docker load -i mysql-5.7-arm64.tar.gz docker tag mysql:5.7 harbor.internal.example.com:8080/library/mysql:5.7 docker push harbor.internal.example.com:8080/library/mysql:5.7--platform linux/arm64 这一步很关键。mysql:5.7 官方镜像同时发布 amd64 和 arm64但在 x86 下载机上直接 pulldocker 默认拿 amd64。如果你不管后续推到 ARM 的 Harbor 上虽然文件能进去但任何 ARM 机器再 pull 下来跑都逃不过第 4.1 节的 exec format error。这一条同样适用于 redis、nginx以及 gradle 离线包里偶见的项目镜像。凡是下载材料里没有明确标注架构的pull 时手动指定 --platform能省掉后面一整套排错。5.2 用 skopeo 把 tar.gz 离线包批量推入 Harbor如果离线包是 docker save 出来的 tar.gz又不想在目标机上先 docker load可以装一个 skopeo直接从 tar.gz 复制到 Harbor路径更短也避免临时镜像占满本地磁盘。# 单镜像示例把 tar.gz 里的镜像直接推到 Harbor 指定项目 skopeo copy --dest-creds admin:ChangeMe_2024 \ docker-archive:mysql-5.7-arm64.tar.gz \ docker://harbor.internal.example.com:8080/library/mysql:5.7skopeo 支持从 docker-archive、docker-daemon、dir 等格式复制到 docker://。--dest-creds 是目标仓库的账号密码多个 tar.gz 可以写个循环批量处理。批量脚本里有个容易错的地方tag 写错或漏写会把镜像推成 latest。我一般先解出 tar.gz 里自带的 RepoTags再用它做目标 tag。for f in ./offline-images/*.tar.gz; do image_tag$(tar -xOf $f manifest.json | python3 -c import sys,json; print(json.load(sys.stdin)[0][RepoTags][0])) # 去掉 docker.io 前缀没有项目名的默认放 library repo${image_tag#docker.io/} case $repo in */*) ;; *) repolibrary/$repo ;; esac skopeo copy --dest-creds admin:ChangeMe_2024 \ docker-archive:$f \ docker://harbor.internal.example.com:8080/${repo} done这段脚本会读取 docker save 生成的 manifest.json把第一个 RepoTags 作为目标仓库和 tag批量推到 Harbor。如果 tar.gz 里的镜像名带 docker.io/library/redis:7.0.12去掉 docker.io 前缀后就是 library/redis:7.0.12正好和目标 Harbor 的项目结构对应如果 tag 是 nginx:latest 这种没有项目名的脚本会自动补成 library/nginx:latest。跑的时候注意看输出里的 copying 状态不要中断。5.3 给 KubeKey 私有仓库喂镜像的几个注意点KubeKey 是常用的 Kubernetes 离线部署工具部署时会把组件镜像从镜像仓库拉取。它默认使用 Docker Hub生产环境会改成私有仓库。常见做法是先把 KubeKey 需要的镜像 tar.gz 全部推到 Harbor再把 KubeKey 配置里的镜像仓库地址指向 Harbor。这一节说几个注意点不展开具体集群配置。第一KubeKey 的离线镜像包有可能包含多架构内容具体按下载页说明确认。直接 docker load 后 docker push 到 Harbor推上去的一般是本机平台对应的镜像如果后续集群里有不同架构的节点拉取时可能拿不到对应内容。稳妥的做法是先用 skopeo copy 把多架构整个复制过去或者确保下载包就是目标架构的单一架构版本。第二Harbor 的项目权限。KubeKey 拉取镜像时不会做额外鉴权配置离线环境里我习惯把 KubeKey 用到的项目设为公开项目或者配好 robot 账号再把 robot 账号的凭据写到节点的 docker config 里。两个方式都行公开项目省事robot 账号更安全。第三证书问题。如果 Harbor 用了自签 HTTPS每个节点都要信任这个 CA否则 docker 拉镜像会报 x509 错误。离线环境里这个坑很常见很多实施文档到这一步就直接卡住。要么把 CA 分发到 /etc/docker/certs.d/Harbor地址/要么就用 HTTP 并在 docker daemon 配置里把 Harbor 地址加到 insecure-registries。选后者居多因为离线环境网络可控。注意离线环境里给 docker 配 insecure-registries 前先确认网络部署的隔离程度内网可控前提下这是最省事的做法。6. 升级与备份让 v2.8.2 的环境不再难以收场Harbor 升级最怕的不是镜像丢了而是数据库和配置漂移。从 v2.8.2 升级到更高版本我的顺序永远是先备份、再改配置、最后才动 install.sh。备份不是简单把目录拷走流程是这样的cd /path/to/harbor # 先停掉整套容器保证 PostgreSQL 不会在备份过程中写数据 docker-compose down # 再同步数据卷到备份路径注重数据库的一致性 sudo rsync -a /data/harbor /backup/harbor-backup-$(date %Y%m%d) # 配置文件单独存一份 cp harbor.yml harbor.yml.$(date %Y%m%d) # 备份完成后重新启动 docker-compose up -d先 docker-compose down 再 rsync比容器还在运行时直接拷贝数据目录可靠得多。Postgres 运行期间直接拷数据文件容易出现 WAL 和主数据文件不在同一时间点的问题恢复出来可能启动失败。这个备份顺序算是我长期维护 Harbor 的一个固定习惯。升级时下载新版本的 arm64 离线包解压后对比新版 harbor.yml.tmpl 和旧版 harbor.yml把新出现的配置项补齐但 data_volume 不要改成新路径否则新版本容器会拿到空数据看起来像是镜像全丢了。Harbor 的 PostgreSQL 在首次启动时会做自动 migration这个动作依赖老数据目录里的库文件。还有一个习惯值得长期保留每次改完 harbor.yml不要只执行 docker-compose restart。很多配置是容器创建时注入的restart 不会重新创建容器改完等于没改。我一般用docker-compose down docker-compose up -d这套 down 再 up 的方式会让 compose 按新配置重建容器虽然比 restart 多几秒但能避免“我明明改了配置怎么没生效”的疑惑。我自己维护的几套 ARM 环境一直用这个流程做升级和配置变更没因为备份或者迁移丢过镜像和配置。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。