Harbor v2.9.0 arm64离线安装实战:镜像架构校验与避坑指南

发布时间:2026/9/29 14:15:49
Harbor v2.9.0 arm64离线安装实战:镜像架构校验与避坑指南 简介本资源为 Harbor v2.9.0 的 arm64 架构离线安装包面向需要在国产化或 ARM 服务器环境中私有化部署容器镜像仓库的运维与开发人员。相比在线安装方式离线包可规避网络受限、镜像拉取失败等问题适合内网、信创及边缘计算等场景快速落地。压缩包共 6 个文件以 sh 安装脚本、gz 离线镜像包为主另含 license、prepare 及 tmpl 配置模板整体约 722.35MB执行 install.sh 即可一键完成部署前置依赖为 docker 与 docker-compose。目前已有 962 人学习下载说明该方案在 ARM 环境下具备一定参考价值。借助该资源读者可省去逐层拉取镜像与手工配置的繁琐过程直接获得可运行的 Harbor 仓库环境并依据模板文件调整端口、存储与认证参数为后续镜像推送、权限管理和 CI/CD 集成打下基础。1. Harbor v2.9.0 离线安装arm架构一次把离线包、镜像和依赖全钉死在麒麟 V10、银河麒麟这类 arm64 服务器上装 Harbor v2.9.0最让人头疼的不是 Harbor 本身而是「离线」两个字。x86 上随手docker pull就能解决的事到了 arm 架构、内网隔离、没有外网 DNS 的环境里就变成了一场依赖链的排查战。Harbor v2.9.0 的离线安装包官方只提供 amd64 版本arm64 需要自己从源码构建或找第三方构建产物而它依赖的 PostgreSQL、Redis、Nginx、Trivy 等组件镜像也必须是 arm64 架构否则docker-compose up时会直接报exec format error。这篇内容面向的是需要在 arm 架构 Linux 服务器上、无外网条件下部署私有镜像仓库的运维和平台工程师从离线包准备、镜像架构校验、docker-compose 配置到安装后排错一步步把这条路走通。如果你手上正好有一台麒麟 arm 服务器和一个 U 盘那就可以直接跟着做。2. 离线包与 arm64 镜像的准备从哪拿到能用的东西2.1 为什么官方离线包在 arm 上直接翻车Harbor 官方 release 页面提供的harbor-offline-installer-v2.9.0.tgz是 amd64 架构的里面打包的 9 个组件镜像全部是linux/amd64。你把这个包拿到 arm64 服务器上解压、执行./install.shdocker 会尝试运行这些镜像然后立刻报错standard_init_linux.go:228: exec user process caused: exec format error这个错误的本质是 CPU 指令集不匹配。arm64 和 amd64 是两套完全不同的指令集docker 不会自动转译除非你装了 qemu-user-static 做 binfmt 模拟但生产环境不建议这么做性能损耗大且部分组件会出玄学问题。所以 arm 架构下的离线安装核心思路是自己构建或获取 arm64 版本的 Harbor 组件镜像然后替换离线包中的镜像列表。常见做法有三种方案适用场景优点缺点源码构建全部组件镜像有 arm 构建机、要求完全自主可控性最强耗时长依赖 Go/Node 编译环境使用第三方 arm64 构建产物内网急用、信任来源省时来源需自行验证在有网的 arm 机器上 docker pull 后导出有一台能联网的 arm 机器操作简单需要一台 arm 联网机我一般会选第三种找一台能联网的 arm64 机器云上的 arm 实例也行把 Harbor v2.9.0 需要的所有镜像 pull 下来docker save导出成 tar 包再拷贝到内网服务器上docker load。这样最稳妥镜像来源就是官方 registry只是换了架构。2.2 用 docker save/load 搬运 arm64 镜像Harbor v2.9.0 依赖的组件镜像清单如下以官方 docker-compose 模板为准# 在联网的 arm64 机器上执行 # 定义镜像列表对应 Harbor v2.9.0 的组件 IMAGES( goharbor/harbor-core:v2.9.0 goharbor/harbor-portal:v2.9.0 goharbor/harbor-jobservice:v2.9.0 goharbor/harbor-registryctl:v2.9.0 goharbor/registry-photon:v2.9.0 goharbor/nginx-photon:v2.9.0 goharbor/harbor-db:v2.9.0 goharbor/redis-photon:v2.9.0 goharbor/trivy-adapter-photon:v2.9.0 goharbor/harbor-exporter:v2.9.0 ) # 逐个拉取并导出 for img in ${IMAGES[]}; do echo Pulling $img ... docker pull $img # 将镜像名中的 / 和 : 替换为 _ 作为文件名 fname$(echo $img | tr /: __) docker save $img -o /tmp/harbor-arm64/${fname}.tar done # 打包所有 tar 文件 tar czf harbor-arm64-images-v2.9.0.tar.gz -C /tmp/harbor-arm64 .逻辑说明这段脚本做了三件事——拉取每个组件镜像、用docker save导出为独立 tar 文件、最后统一打包成一个压缩包。docker save保留镜像的完整层信息和元数据docker load到目标机器后镜像 ID 和 tag 都不变。参数说明IMAGES数组里的 tag 必须和 Harbor v2.9.0 的docker-compose.yml中引用的完全一致差一个字符都会导致install.sh找不到镜像。如果你的 Harbor 版本略有不同去解压后的docker-compose.yml里搜image:字段确认实际 tag。注意docker save导出的 tar 文件体积可能达到 2-3 GB确保/tmp分区有足够空间。如果镜像拉取时提示no matching manifest for linux/arm64说明该组件没有官方 arm64 构建需要自行从源码编译。2.3 离线包的目录结构与替换策略官方离线包解压后的目录结构是这样的harbor/ ├── harbor.v2.9.0.tar.gz # 原始 amd64 镜像包需要替换 ├── harbor.yml.tmpl # 配置模板 ├── install.sh # 安装脚本 ├── prepare # 预处理脚本 ├── docker-compose.yml # 服务编排文件 └── common.sharm 架构下的替换策略把harbor.v2.9.0.tar.gz替换成你自己导出的 arm64 镜像包或者干脆不走install.sh的自动加载流程手动docker load后再执行docker-compose up -d。我一般会这样做# 在目标 arm64 服务器上操作 # 1. 解压官方离线包只取配置文件部分 tar xzf harbor-offline-installer-v2.9.0.tgz cd harbor # 2. 删除 amd64 镜像包避免误加载 rm -f harbor.v2.9.0.tar.gz # 3. 加载自己搬运过来的 arm64 镜像 docker load -i /path/to/harbor-arm64-images-v2.9.0.tar.gz # 4. 确认所有镜像架构正确 docker images --format {{.Repository}}:{{.Tag}}\t{{.Size}} | grep goharbor逻辑说明先解压官方包拿到配置模板和脚本然后删掉 amd64 镜像包防止install.sh自动加载错误的镜像。手动docker load后再确认镜像列表。参数说明docker load -i支持加载.tar和.tar.gz格式如果是多个独立 tar 文件需要逐个加载或先合并。docker images的--format参数可以自定义输出方便脚本化检查。3. harbor.yml 配置与 docker-compose 适配 arm 环境3.1 harbor.yml 里必须改的 5 个参数Harbor 的主配置文件是harbor.yml从harbor.yml.tmpl复制而来。在 arm 离线环境下以下参数必须确认# harbor.yml 关键配置段 hostname: harbor.internal.example.com # 必须是内网可解析的域名或 IP http: port: 80 # 如果 80 被占用改成其他端口 https: # 离线环境没有证书就注释掉整个 https 段 # port: 443 # certificate: /your/certificate/path # private_key: /your/private/key/path harbor_admin_password: Harbor12345 # 首次登录密码装完立刻改 database: password: root123 # 内部数据库密码建议改掉 max_idle_conns: 100 data_volume: /data # 镜像存储路径确保分区够大 trivy: ignore_unfixed: false skip_update: true # 离线环境必须设为 true offline_scan: true # 离线扫描模式逐个说明hostname是 Harbor 对外提供服务的地址客户端docker login时用的就是这个值。离线内网环境填 IP 或内网 DNS 域名都行但一旦确定就不要改因为镜像的引用路径里会包含这个 hostname。https段在离线环境里如果没有正式证书直接注释掉用 HTTP 访问。生产环境建议还是配证书但离线自签证书需要把 CA 分发到所有客户端。trivy.skip_update和trivy.offline_scan是离线环境的关键配置。Trivy 默认会去外网更新漏洞库离线环境下会卡住或报错必须关掉自动更新。data_volume默认是/dataHarbor 的所有镜像层、数据库文件、日志都在这个目录下。生产环境建议单独挂一块盘。3.2 docker-compose.yml 中镜像引用的架构校验install.sh执行prepare脚本时会根据harbor.yml生成最终的docker-compose.yml。在 arm 环境下你需要确认生成的 compose 文件里所有image:字段引用的镜像都已经在本地存在且架构正确。# 生成 docker-compose.yml 但不启动服务 ./prepare # 检查 compose 文件中引用的所有镜像 grep image: docker-compose.yml | awk {print $2} | sort -u # 逐个确认本地是否存在对应镜像 for img in $(grep image: docker-compose.yml | awk {print $2} | sort -u); do if docker image inspect $img /dev/null 21; then arch$(docker image inspect $img --format {{.Architecture}}) echo OK: $img (arch: $arch) else echo MISSING: $img fi done逻辑说明./prepare会根据harbor.yml渲染出最终的docker-compose.yml但不会启动容器。然后从 compose 文件中提取所有镜像名逐个用docker image inspect检查本地是否存在并输出架构信息。参数说明docker image inspect的--format参数用 Go template 语法{{.Architecture}}取镜像架构字段。arm64 机器上应该输出arm64如果输出amd64说明加载了错误的镜像。如果发现某个镜像缺失或架构不对需要回到第 2 章重新导出对应的 arm64 镜像。3.3 用 docker-compose 手动启动并验证确认所有镜像就绪后可以手动启动# 启动所有 Harbor 服务 docker-compose up -d # 查看容器状态确认没有反复重启的 docker-compose ps # 查看 harbor-core 日志确认数据库连接正常 docker-compose logs -f harbor-core逻辑说明docker-compose up -d后台启动所有服务。docker-compose ps查看状态正常的容器状态应该是Up而不是Restarting或Exit。harbor-core是核心服务它的日志能反映数据库连接、配置加载等关键信息。参数说明-d表示 detached 模式后台运行。logs -f持续输出日志CtrlC退出但不停止容器。启动后访问http://hostname用admin和harbor.yml里配置的密码登录。能登录进去、能看到项目列表说明基本部署成功。4. 离线安装避坑5 个血泪踩坑记录4.1 坑一exec format error——镜像架构不匹配现象docker-compose up -d后容器反复重启docker-compose logs看到exec user process caused: exec format error。原因加载了 amd64 架构的镜像。常见于直接用了官方离线包里的harbor.v2.9.0.tar.gz或者从 x86 机器上docker save后搬过来的镜像。解决用docker image inspect image --format {{.Architecture}}逐个检查确保所有 goharbor 镜像都是arm64。如果是 amd64回到第 2 章重新在 arm64 机器上拉取导出。4.2 坑二Trivy 卡在更新漏洞库现象trivy-adapter-photon容器启动后一直处于starting状态日志显示Updating DB...然后卡住不动。原因Trivy 默认会从外网拉取漏洞数据库离线环境没有外网连接导致超时或无限等待。解决在harbor.yml中设置trivy.skip_update: true和trivy.offline_scan: true然后重新执行./prepare和docker-compose up -d。如果已经启动过先docker-compose down再重新来。4.3 坑三PostgreSQL 数据目录权限问题现象harbor-db容器启动失败日志报FATAL: data directory /var/lib/postgresql/data has wrong ownership或could not open directory。原因Harbor 的 PostgreSQL 容器以非 root 用户运行而data_volume指定的宿主机目录权限不对。常见于手动创建了/data目录但没有设置正确的属主。解决# 查看 harbor-db 容器实际使用的 UID docker-compose logs harbor-db | grep -i uid # 通常 PostgreSQL 容器内用户 UID 是 999 chown -R 999:999 /data/database如果用的是 NFS 挂载还需要确认 NFS 的no_root_squash或all_squash配置否则容器内用户会被映射成nobody。4.4 坑四hostname 配了域名但内网 DNS 解析不了现象Harbor 服务全部Up但浏览器访问http://harbor.internal.example.com打不开docker login也报no such host。原因harbor.yml里配了一个内网 DNS 域名但客户端机器的 DNS 没有配置对应的解析记录。解决两个办法——要么在 DNS 服务器上加 A 记录要么在所有需要访问 Harbor 的机器上改/etc/hosts。如果只是测试直接把hostname改成服务器 IP 最省事。但注意改了 hostname 后需要重新./prepare并重启而且之前推送的镜像路径会失效。4.5 坑五磁盘空间不足导致镜像推送失败现象docker push推送到一半报received unexpected HTTP status: 500 Internal Server ErrorHarbor 日志显示no space left on device。原因data_volume所在分区满了。Harbor 的镜像存储、数据库、Redis 持久化、日志都在这个分区下默认/data如果跟根分区共用很容易被占满。解决# 查看 data_volume 分区使用率 df -h /data # 清理 Harbor 的旧日志不会影响镜像数据 find /data/log -name *.log -mtime 7 -delete # 如果确实需要扩容把 data_volume 迁移到更大的分区 # 1. 停止 Harbor docker-compose down # 2. 迁移数据 rsync -avz /data/ /new-disk/harbor-data/ # 3. 修改 harbor.yml 中的 data_volume # 4. 重新 prepare 并启动 ./prepare docker-compose up -d提示Harbor 自带垃圾回收功能可以在 Web UI 的「系统管理 → 垃圾回收」里手动触发清理没有被任何 tag 引用的镜像层。但注意 GC 期间 Harbor 会进入只读模式建议在业务低峰期操作。5. 装完之后验证清单与一个提效技巧Harbor 跑起来只是第一步确认它真的能用、能扛住日常推送拉取才算部署完成。我一般会按下面这个清单过一遍验证项操作预期结果Web UI 登录浏览器访问 hostnameadmin 登录正常进入项目列表创建项目新建一个私有项目 test创建成功可见推送镜像docker tagdocker push推送成功UI 可见拉取镜像docker pull刚推送的镜像拉取成功重启恢复docker-compose down再up -d数据不丢服务正常日志检查docker-compose logs无 ERROR无持续性错误推送测试的具体命令# 在客户端机器上操作 # 1. 登录 Harbor docker login harbor.internal.example.com -u admin -p Harbor12345 # 2. 给本地镜像打 tag docker tag nginx:latest harbor.internal.example.com/test/nginx:latest # 3. 推送 docker push harbor.internal.example.com/test/nginx:latest # 4. 删除本地镜像后重新拉取验证仓库确实存了 docker rmi harbor.internal.example.com/test/nginx:latest docker pull harbor.internal.example.com/test/nginx:latest逻辑说明这个流程覆盖了登录认证、镜像推送、镜像拉取三个核心操作。第 4 步先删本地再拉取确保拉到的确实是从 Harbor 服务器来的而不是本地缓存。参数说明docker login的-p参数明文传密码只适合脚本里用手动操作建议不加-p交互式输入更安全。docker tag的格式是harbor-hostname/project/image:tagproject 必须是在 Harbor 里已创建的项目名。一个提效技巧如果你有多台 arm 服务器需要装 Harbor可以把整个/data目录和docker-compose.yml打包在新机器上解压后直接docker-compose up -d省去重复prepare的步骤。但要注意新机器的hostname如果不同需要改harbor.yml后重新prepare否则客户端推送路径对不上。最后说一个我踩过的坑Harbor 的install.sh脚本在 arm 环境下会尝试加载harbor.v2.9.0.tar.gz如果你忘了删这个文件它会静默加载 amd64 镜像然后启动失败日志里只报exec format error不告诉你是哪个镜像的问题。所以我现在养成的习惯是——解压官方包后第一件事就是rm -f harbor.v2.9.0.tar.gz然后手动docker load自己的 arm64 镜像包每一步都确认架构不依赖脚本的自动流程。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询