ARM64环境Harbor 2.8.2离线安装与镜像推送避坑指南 简介面向ARM 64位架构的Harbor 2.8.2离线安装包专为在无外网或受限网络环境中部署容器镜像仓库的运维与开发人员准备。资源共6个文件包括安装脚本、环境准备工具、公共函数库、配置模板、许可文件及核心镜像离线包可完整支撑Harbor在ARM服务器上的静默安装与配置无需从公网拉取额外组件。离线包约639.65MB体积控制得当便于内网传输、离线分发和批量部署。已有261人学习下载适合边缘计算、物联网、信创及私有化部署场景。借助该包用户可快速搭建企业级镜像仓库启用权限控制、镜像复制与漏洞扫描能力并支持LDAP/AD等身份认证集成。对于需要在国产化ARM设备上高效交付Harbor服务的团队这是一款开箱即用、省时省力的基础资源。1. 先别急着解压arm 环境的 Harbor 2.8.2 离线包落地前要把这三件事想清楚拿到harbor-offline-installer-v2.8.2-arm64.tar.gz多数人第一步就是解压、改harbor.yml、跑install.sh。在 x86 服务器上这条路很顺但换成 arm 环境后同样的操作往往会在加载镜像、权限校验、架构匹配这些环节上卡住。这份离线包解决的问题是把 Harbor 2.8.2 的所有依赖容器以 arm64 镜像形式一次性带到内网绕过在线拉取的不确定因素。它的适用对象很明确只有 arm64 服务器的私有化环境以及希望在断网或弱网条件下把镜像仓库立起来的团队。下面从环境自查、离线安装、镜像推送写到备份升级全程用可以直接复制的命令并标注那些只有真正在 arm 上装过才会遇到的边界条件。2. 环境自查与前置准备arm64 离线包不是解压就能跑的2.1 先确认机器是 arm64三条命令看清真实架构arm 这个词在工程里被用得很乱。有人说的 arm 指 32 位的 armv7有人说的是服务器级的 aarch64也就是 armv8 的 64 位指令集。harbor-offline-installer-v2.8.2-arm64.tar.gz里的arm64明确指向后者所以在动手之前先要在目标机器上确认架构否则后面每一步都可能因为镜像平台不匹配而中断。uname -m lscpu | grep Architecture cat /proc/cpuinfo | grep -E model name|CPU architecture | head -5第一行uname -m是判断架构最直接的方式输出aarch64才是这个离线包的目标平台输出armv7l或armhf说明机器是 32 位 arm需要换对应架构的 Harbor 包不要硬装。第二行lscpu能看到完整架构信息第三行用来确认具体 CPU 型号方便后续排查内核与虚拟化相关的问题。无论是物理服务器、云实例还是虚拟机只要三条命令的结果指向 aarch64这个离线包就可以继续往下走。确认完架构还要看一眼操作系统内核版本。Harbor 的容器运行时依赖 docker daemon而 docker daemon 对内核版本有明确要求。常见做法是用uname -r查看内核如果小于 4.0建议先升级系统内核否则容器在初始化 cgroup 时可能报错这类问题在 arm 的单板设备上比 x86 更容易遇到因为很多 arm 板子出厂带的是非常老的定制内核。2.2 依赖组件检查docker、docker compose 与系统工具Harbor 2.8.2 的安装脚本依赖两个核心组件docker 和 docker compose。需要注意Harbor 2.8 系列使用的是 docker compose v2也就是集成在 docker CLI 里的docker compose子命令而不是早年那种独立的docker-compose二进制。如果目标机器上只有旧版独立二进制安装脚本会在前置检查阶段直接报错根本走不到部署那一步。docker version --format {{.Server.Version}} docker compose version openssl version tar --version | head -1 free -h df -h /data上面这段命令把后续安装会用到的工具一次性查完。docker version确认 server 端版本在 20.10 以上docker compose version确认 v2 插件存在openssl和tar是解压和证书生成阶段的依赖最后两行看内存和磁盘。建议内存不低于 4GB至少预留 20GB 磁盘空间给 Harbor 的数据目录。离线包本身和启动后的镜像、数据库日志都会落在data_volume上磁盘太满会导致 registry 容器反复重启这类问题排查起来非常消耗时间。在离线环境下还有一个容易被忽略的点整个安装过程不会去外网拉任何东西但前提是 docker 本身已经装好。如果目标机器连 docker 都没有那就得先用离线 deb/rpm 包把 docker 装好再回来跑 Harbor 的离线包。我习惯把这一步单独写成一段检查脚本避免人工漏看if [ $(uname -m) ! aarch64 ]; then echo 架构不匹配当前是 $(uname -m) exit 1 fi if ! docker version /dev/null 21; then echo docker 未安装或无法访问 docker daemon exit 1 fi if ! docker compose version /dev/null 21; then echo 缺少 docker compose v2 插件 exit 1 fi echo preflight OK这段脚本的逻辑是逐项卡住最关键的三个前置条件任何一个不满足就立刻退出而不是等到install.sh跑了一半才暴露问题。参数说明uname -m判断架构docker version同时检查 docker 客户端和 daemon 是否可用docker compose version判断 v2 子命令是否存在。注意脚本里没有检查内存和磁盘因为这两个值在安装过程中可以用free和df人工确认写死在脚本里反而会在不同机器上产生误判。做完这些检查就可以进入真正的安装环节。前置准备这一段花十分钟能省掉后面一两个小时的无头绪排查。3. 离线安装全流程从解压 tar.gz 到 Harbor 页面可访问3.1 解压与 harbor.yml 配置三个必改项离线包的解压没有特殊之处tar 命令就能完成。解压后会出现一个 harbor 目录里面除了install.sh和prepare还有harbor.yml、harbor.yml.tmpl、common.sh等文件。install.sh是入口脚本prepare负责生成运行时配置harbor.yml是唯一需要人工修改的配置文件。tar -xzf harbor-offline-installer-v2.8.2-arm64.tar.gz cd harbor ls -la解压完成后ls -la可以看到上述文件。注意整个解压过程不涉及 root 权限但后续install.sh需要 root 权限因为要创建容器和挂载目录。接下来打开harbor.yml这个文件是 YAML 格式缩进错误会导致后续prepare阶段报错。需要修改的配置项并不多但有几个是必须改的不然装完也用不了。配置项默认值建议改为什么作用hostnamereg.mydomain.com当前机器的 IP 或内网 DNS 名决定访问地址和镜像仓库的完整路径http.port80与现有服务冲突时改为 8080 等端口Harbor 对外提供 HTTP 服务的端口harbor_admin_passwordHarbor12345内网强密码管理员 admin 的初始登录密码data_volume/data独立数据盘目录存放镜像、数据库、日志的持久化目录hostname必须改成实际能访问到这台机器的地址。如果配的是域名客户端需要在 DNS 里解析到这台机器如果配的是 IP页面登录时会有一条 URL 不匹配的警告但不影响功能。http.port默认 80很多 arm 服务器上 80 已经被其他服务占用改成 8080 是常见操作。harbor_admin_password是安装时写死到数据库里的初始密码安装之后在页面上修改不会同步回这个文件。data_volume建议指到一块独立的数据盘而不是根目录否则镜像多了以后根分区被撑满整个系统都会出问题。下面是一份最小可用的配置片段hostname: 192.168.10.20 http: port: 8080 harbor_admin_password: Admin2024 data_volume: /data/harbor这段配置把服务绑定在192.168.10.20:8080管理员密码设为Admin2024数据落盘在/data/harbor。如果本机有 python3建议在保存之后先做一次 YAML 语法校验python3 -c import yaml; yaml.safe_load(open(harbor.yml))这个命令会把harbor.yml读入并解析如果缩进或引号有问题会立即抛出异常没有任何输出就说明格式没问题。很多人在这里直接跳过校验结果安装时报unexpected end of stream排查起来才知道是 yaml 语法错误浪费时间。3.2 执行 install.sh选对参数一步到位配置写完接下来是执行安装脚本。最简形式是直接运行sudo ./install.sh脚本会自动检查依赖、加载离线包内的镜像 tarball、调用 prepare 生成 compose 配置然后用 docker compose 启动全部容器。cd harbor sudo ./install.sh # 前置检查通过后所有镜像由离线包内自动加载如果想要漏洞扫描能力可以带--with-trivy参数这样会额外启动一个 trivy 容器用于扫描镜像漏洞。如果不需要扫描功能建议先不加这个参数trivy 会占用额外内存在内存紧张的内网 arm 服务器上这往往是压垮系统的最后一根稻草。安装过程中会看到脚本输出从检查环境到加载镜像、生成配置、启动容器的一系列进度。如果机器性能一般镜像加载和容器启动会持续几分钟这是正常的。真正需要警惕的是脚本在中途异常退出退出码为 1这类问题的处理我放在第 5 章详细讲。安装完成后先看容器状态cd harbor sudo docker compose ps curl http://localhost:8080/api/v2.0/pingdocker compose ps应该看到log、registry、core、portal、db、jobservice、redis这些服务全部处于 Running 状态。如果有容器反复重启或者处于 Exited 状态用sudo docker compose logs 服务名查看对应日志。curl探测的路径是 Harbor 的 API 健康检查接口正常会返回一个Pong字符串。这里直接用 HTTP 探测即可因为默认harbor.yml里没有启用 HTTPS。如果是在远程执行把 localhost 换成实际 IP 或域名。到这里Harbor 已经算是装起来了。浏览器访问http://192.168.10.20:8080用 admin 和配置的密码登录就能看到管理界面。但“页面能开”只代表服务活着真正判断一个私有镜像仓库能不能用要看它是否支持客户端推送和拉取镜像这是下一章的内容。4. 仓库初始化与镜像推送arm64 离线包装完怎么才算“能用”4.1 客户端配置把 docker 的“不信任”改掉Harbor 装好之后客户端默认是连不上它的。原因在于 docker 客户端对待 HTTP 和 HTTPS 的策略默认情况下dockerd 只信任 HTTPS 的 registry 地址而我们在harbor.yml里配置的是 HTTP。这时候如果不做任何设置docker login会直接报错。解决方式有两种一是给 Harbor 配正规的 HTTPS 证书二是让 docker 对这个地址放行 HTTP后者在 arm 开发环境里更常见。sudo tee /etc/docker/daemon.json EOF { insecure-registries: [192.168.10.20:8080] } EOF sudo systemctl restart dockerinsecure-registries告诉 dockerd访问192.168.10.20:8080这个地址时不要强制 TLS 校验。配置完必须重启 docker否则配置不生效。这里有一个很容易踩的细节数组里必须写完整的IP:端口只写 IP 的话docker 不会把带端口的地址视为不安全的 registry登录时依然会尝试 HTTPS。重启之后先确认配置生效再登录docker info | grep -i insecure docker login 192.168.10.20:8080docker info输出里会列出所有 insecure registry 地址看到刚配置的哪一行就说明生效了。登录时输入 admin 和之前设置的密码出现Login Succeeded就说明客户端与 Harbor 之间已经打通。如果报错大概率是daemon.json语法有误或者 docker 没重启成功用sudo systemctl status docker看一眼就能定位。这里需要说明一个选型判断insecure-registries 适合内网和测试环境生产环境还是应该走 HTTPS。arm 环境里很多团队为了省事一路 HTTP 用到底但如果 Harbor 要暴露给多个网段的客户端建议至少用自签证书并把 CA 分发到各客户端否则每次新接入一台机器都要手工改 daemon.json。两种方式二选一不要混用混用最容易出现“这台机器能登录、那台机器报 x509”的诡异局面。4.2 推一个 arm64 镜像完整的 tag-push-pull 闭环登录成功之后第一件要做的事情是确认要推送的镜像本身是 arm64 架构。Harbor 只是一个镜像仓库它不会做跨架构转换推送上去是什么架构拉取时就会匹配什么架构。docker image inspect --format {{.Architecture}} busybox如果输出不是arm64而是amd64说明这个镜像在 x86 上拉取过架构不对。在 arm64 节点上想拿到正确架构的镜像常见做法是显式指定平台重新拉取docker pull --platform linux/arm64 busybox:latest docker image inspect --format {{.Architecture}} busybox--platform参数会强制拉取 manifest 列表中 arm64 版本的镜像。拉取完成后 inspect 输出arm64就可以继续下一步了。docker tag busybox:latest 192.168.10.20:8080/library/busybox:latest docker push 192.168.10.20:8080/library/busybox:latestdocker tag的作用是给本地镜像打上目标 registry 的完整地址标签docker push会按标签里的地址把镜像上传到 Harbor。library是 Harbor 默认创建的一个公共项目推送进去之后所有客户端都能拉取。在另一台同样配置了 insecure-registries 的 arm 节点上执行docker pull 192.168.10.20:8080/library/busybox:latest能正常拉下来整个推拉闭环就算打通了。如果拉取时报no matching manifest for linux/arm64说明推送上去的镜像不是 arm64 架构回到上面用--platform linux/arm64重新拉取并 tag 推送。这个错误是 arm 环境里跑镜像仓库最常遇到的坑本质上是镜像内容与运行平台的匹配问题跟 Harbor 本身没有关系。5. 避坑arm 环境安装 Harbor 最容易翻车的 4 个问题5.1 现象install.sh 执行到一半报错exit code 1在 arm 服务器上跑sudo ./install.sh前置检查全部通过但脚本在启动容器阶段中断最后只留下一行 exit code 1。这个问题我在 arm 环境里遇到过不止一次原因通常有两个。第一个原因是 docker compose 版本不对。Harbor 2.8.2 的 compose 配置文件依赖 docker compose v2 的语法如果宿主机上的 compose 是旧版独立二进制解析就会失败。解决方式是确认docker compose version能正常输出 v2 版本号必要时升级 docker。第二个原因是之前有过一次失败安装残留的容器或数据目录占住了位置。解决方式是先清理再重跑cd harbor sudo docker compose down sudo docker ps -a | grep harbor | awk {print $1} | xargs docker rm -f sudo rm -rf /data/harbor/database sudo ./install.sh注意最后一步删数据库目录要慎重只有确认数据不需要保留时才执行。如果数据很重要应该备份而不是删除。这一段的操作逻辑是docker compose down只停容器不删数据rm -rf database才是真正清空数据库顺序不能反。另外一个容易忽略的问题部分 arm 板子用的老内核跑 docker 时容器初始化 cgroup 会失败从日志里能看到与 namespace 或 cgroup 相关的报错这种情况下只能升级内核没有捷径。5.2 现象docker login 报 x509certificate signed by unknown authority客户端已经配了insecure-registries登录时仍然报x509: certificate signed by unknown authority。这个现象的原因往往不在 Harbor而在 daemon.json 的配置没有真正生效。排查步骤是先重启 docker再确认配置被正确加载sudo systemctl restart docker docker info | grep -i insecure如果docker info里看不到刚配置的地址说明 daemon.json 的语法可能有误或者路径不对。另外要确认 daemon.json 里没有同时配置多个 registry 服务导致格式变成 JSON 数组嵌套错误。还有一种情况是 Harbor 启用了 HTTPS而客户端只配了 HTTP 的 insecure。两者必须一致Harbor 用 HTTP客户端就配 insecureHarbor 用 HTTPS 加自签证书客户端就应该把 CA 放到/etc/docker/certs.d/hostname:port/ca.crt。我自己的血泪经验是不要一半机器走 insecure、一半机器走证书统一一种方式否则每接入一台新机器都要现场改配置。如果排查时想快速定位问题可以先看 docker daemon 的日志sudo journalctl -u docker --since 5 minutes ago | grep -i insecure这条命令能直接看到 dockerd 启动时有没有加载 insecure-registries 配置。如果日志里没有相关记录说明配置文件没有被读取优先检查路径和 JSON 语法。5.3 现象镜像推送到一半失败或者 push 成功但 pull 报 manifest 不匹配推送一个几十 GB 的大镜像进度条到 90% 左右断掉重试几次还是断在同一个位置。这个问题在 arm 内网环境里多半不是 Harbor 的锅而是客户端与 Harbor 之间的网络链路不稳定尤其是跨网段推送大文件时TCP 连接很容易被中间设备掐断。解决方式有两个方向。一是在网络条件改善后再推二是不走 docker push改用镜像归档文件直接传输。后一种在离线环境里反而更稳妥docker save 192.168.10.20:8080/proj/app:arm64 | gzip app-arm64.tgz scp app-arm64.tgz node2:/tmp/ docker load app-arm64.tgzdocker save把镜像导出为 tar 流gzip压缩后通过scp拷贝到目标节点docker load再导入。这个方案绕开了 docker push 对网络的要求适合大镜像跨网段同步。另一种常见的失败是 push 成功但到另一台机器 pull 时报no matching manifest for linux/arm64。这种情况的根本原因是推送时用了 amd64 镜像解决方式是先docker pull --platform linux/arm64拉取正确架构再重新 tag 和 push与第 4.2 节的处理方式一致。要注意docker save和docker load是一对操作不要在中间环节混入其他工具否则镜像 meta 信息容易丢失。5.4 现象页面能打开但 docker push 总在连接阶段超时Harbor 页面在浏览器里能正常打开但在客户端执行docker push时长时间卡住最后报连接超时。这个现象看起来矛盾实际原因通常是 HTTP 与 HTTPS 协议不一致。浏览器访问http://192.168.10.20:8080没问题但客户端 push 时如果daemon.json里没有配置完整的IP:端口docker 会默认用 HTTPS 去连 Harbor而 Harbor 只监听 HTTPTCP 握手之后协议不匹配连接就挂在那里直到超时。解决方式是检查并修正 daemon.jsoncat /etc/docker/daemon.json重点看insecure-registries数组里是否包含完整的192.168.10.20:8080而不是只有 IP。改完之后重启 docker再重新 push。如果确认配置没问题还需要排除磁盘写满的情况用df -h看 Harbor 的data_volume所在分区磁盘满时容器的写操作会异常卡顿表现也是 push 超时。最后还可以用curl -v http://192.168.10.20:8080/v2/从客户端侧探一下 Harbor 的 registry API 是否响应如果 curl 都卡住说明是网络链路问题而不是 docker 配置问题。6. 备份与后续升级把 2.8.2 离线包的价值延续到下一次6.1 备份的关键路径与命令Harbor 的配置和数据分散在两个地方一是解压目录里的harbor.yml二是data_volume指向的整个目录。后者包含数据库、镜像存储、job 日志和密钥备份时两者一起打包最省事。tar -czf harbor-backup-$(date %F).tgz \ -C /opt/harbor harbor.yml \ -C /data/harbor database secretkey # secretkey 丢失后数据库敏感字段无法解密这条命令把harbor.yml、database目录和secretkey打包到一个带日期的压缩文件里。secretkey是 Harbor 的加密密钥丢失后虽然镜像还在但数据库内的敏感字段可能无法解密必须和数据库一起备份。恢复时先docker compose down停掉服务再解压覆盖对应路径最后重新运行install.sh。注意恢复用的离线包版本要和备份时的版本一致跨版本恢复必须走升级流程。6.2 升级前先做一次恢复演练Harbor 2.8.2 升级到更新版本时install.sh 会自动检测旧版本数据并做数据库迁移。但迁移是不可逆操作一旦中间断电或磁盘故障数据可能直接损坏。所以我自己的习惯是每次升级前先把备份恢复到一台临时 arm 机器上跑起来确认所有容器全绿、能正常登录和拉镜像再动正式环境。sudo docker compose ps docker login 临时机器IP:8080 docker pull 临时机器IP:8080/library/app:arm64这三条命令在临时机器上执行通过备份就视为有效。如果恢复后发现某个容器报数据库连接失败多半是备份时容器还在写入数据备份文件不完整下次备份前先docker compose down或者用容器内数据库工具做逻辑导出代替目录拷贝。这套流程我在多个 arm 环境私有化部署中反复使用省下的不止是数据重建的时间还有半夜被叫起来回滚的折腾。希望帮到你。本文还有配套的精品资源点击获取