考试通知
ARM架构离线部署Harbor v2.9.0:镜像架构匹配与排错指南 简介本资源为 Harbor v2.9.0 的 arm64 架构离线安装包面向需要在国产化或 ARM 服务器环境中私有化部署镜像仓库的运维与开发人员。相比在线安装方式离线包可规避网络受限、拉取镜像失败等问题尤其适合内网、信创及边缘计算场景。压缩包共 6 个文件包含 2 个 sh 脚本、1 个 gz 压缩包、1 个 license 授权文件、1 个 prepare 预处理文件及 1 个 tmpl 配置模板整体约 722.35MB覆盖安装脚本、镜像归档与配置模板等核心组件。使用前需预先安装 docker 与 docker-compose执行 install.sh 即可一键完成 Harbor 部署。目前已有 969 人学习下载适合希望快速搭建企业级镜像仓库、减少手工配置成本的中高级运维人员参考使用。1. 离线部署 harbor-v2.9.0 在 arm 架构上到底卡在哪很多团队第一次在 arm 服务器上装 harbor-v2.9.0都会默认「把 x86 那套 docker-compose 流程搬过来就行」结果镜像拉不动、组件起不来、registry 一直 unhealthy。arm 架构的离线安装和 x86 最大的区别不在 harbor 本身而在镜像来源、CPU 架构匹配、以及离线包里每个组件的 manifest 是否真的支持 arm64。harbor-v2.9.0 官方发布的是多架构镜像但离线包默认给的是 amd64 版本直接拿到 arm 机器上docker load会报no matching manifest for linux/arm64。这篇文章面向的是需要在隔离网络、国产化 arm 服务器上落地私有镜像仓库的运维和平台工程师我会把从离线包准备、镜像架构校验、到 harbor 各组件启动排错的完整路径讲清楚包括我踩过的几个血泪坑。读完你能判断自己的 arm 环境能不能直接上以及不能上时该怎么补。2. 离线包与 arm64 镜像的准备工作别让架构不匹配毁掉一整天2.1 先确认你的 arm 机器到底跑的是什么arm 架构不是一个统一概念。服务器上常见的是 aarch64即 arm64但有些边缘设备是 armv7l。harbor-v2.9.0 的官方镜像只提供 linux/arm64不提供 armv7。所以第一步不是下载而是确认目标机器的架构和内核。# 确认 CPU 架构输出 aarch64 才能继续 uname -m # 查看内核版本harbor 2.9 建议 4.19 以上 uname -r # 确认 docker 和 docker compose 是否已安装 docker version --format {{.Server.Version}} docker compose version如果uname -m输出的是armv7l那 harbor-v2.9.0 的官方镜像基本没法直接用需要自行构建成本很高建议换机器或换方案。如果是aarch64继续往下走。docker 版本建议 20.10 以上docker compose 用 v2 插件形式harbor 2.9 的install.sh已经不再依赖 python 版的 docker-compose。2.2 离线包从哪来为什么不能直接用官方 amd64 包harbor 官方发布的 offline installer 默认是 amd64 架构包里的harbor.v2.9.0.tar.gz包含的是 amd64 镜像。在 arm 机器上执行docker load时docker 会检查镜像的 manifest 架构不匹配就直接拒绝。常见做法有两种第一种是找官方或社区提供的 arm64 离线包但 harbor 官方并不总是同步发布 arm64 offline 包所以更可靠的是第二种在一台能联网的 arm64 机器上用 harbor 的在线安装方式先把所有镜像拉下来再导出成离线 tar 包。# 在联网的 arm64 机器上下载 harbor 在线安装包 # 注意这里用的是 online installer不是 offline tar xzvf harbor-online-installer-v2.9.0.tgz cd harbor # 复制配置文件模板 cp harbor.yml.tmpl harbor.yml # 编辑 harbor.yml至少改 hostname 和 harbor_admin_password # 先不改 https用 http 跑通再说编辑harbor.yml时关键字段是hostname写目标机器的 IP 或域名、harbor_admin_password、data_volume。如果只是内网用先把 https 相关配置全部注释掉减少证书带来的变量。# 执行 prepare它会拉取所有需要的镜像 ./prepare # 查看拉下来的镜像列表 docker images | grep goharbor这时候你会看到goharbor/下面一系列镜像包括harbor-core、harbor-portal、harbor-jobservice、registry、registryctl、harbor-db、redis、nginx等。确认这些镜像的架构# 逐个检查镜像架构确保是 arm64 docker inspect goharbor/harbor-core:v2.9.0 --format {{.Architecture}}如果输出arm64说明拉对了。然后把所有镜像导出成一个 tar 包# 导出所有 goharbor 相关镜像 docker save $(docker images | grep -E goharbor|library/redis|library/nginx | awk {print $1:$2}) -o harbor-arm64-images.tar # 查看包大小通常在 2GB 左右 ls -lh harbor-arm64-images.tar这个 tar 包就是你在离线环境里真正需要的东西。把它和 harbor 的安装目录一起拷到目标 arm 机器上。2.3 离线机器上的加载与目录准备目标机器上先确保 docker 已经安装并启动。然后把 tar 包传上去执行加载# 在离线 arm 机器上加载镜像 docker load -i harbor-arm64-images.tar # 确认镜像都在 docker images | grep goharbor加载完成后把 harbor 安装目录放到合适位置比如/opt/harbor。注意harbor.yml里的data_volume指向的目录要提前创建并且有足够空间。registry 存储镜像数据建议单独挂一块盘。# 创建数据目录 mkdir -p /data/harbor # 确认目录权限harbor 容器内以特定 uid 运行 chmod 755 /data/harbor到这里离线包和镜像的准备就算完成。接下来是真正容易翻车的环节启动和排错。3. 用 docker compose 把 harbor 拉起来从 prepare 到首次登录3.1 生成 compose 文件与配置校验harbor 2.9 的prepare脚本会根据harbor.yml生成docker-compose.yml和一堆配置文件。在离线机器上因为镜像已经加载prepare不会再尝试拉取但前提是镜像 tag 和它期望的一致。cd /opt/harbor # 执行 prepare生成 compose 文件 ./prepare # 如果报错找不到镜像检查 tag 是否匹配 # harbor 2.9.0 期望的 tag 通常是 v2.9.0prepare成功后当前目录下会多出docker-compose.yml、common/config/等。重点检查docker-compose.yml里每个服务的image字段确认 tag 和你加载的一致。如果官方在线包拉下来的 tag 是v2.9.0而离线包里的 tag 是v2.9.0那就没问题。不一致时要么改 compose 文件要么重新 tag 镜像。# 如果 tag 不一致用 docker tag 修正 docker tag goharbor/harbor-core:v2.9.0 goharbor/harbor-core:v2.9.03.2 启动顺序与关键参数harbor 的组件有依赖关系db 和 redis 要先起来core 依赖 dbjobservice 依赖 core 和 dbportal 和 nginx 最后。直接docker compose up -d通常没问题compose 会处理 depends_on但离线环境下如果镜像加载不全会出现某个容器反复重启。# 后台启动所有服务 docker compose up -d # 查看容器状态重点看有没有 Restarting 或 Exit docker compose ps正常状态下所有容器应该是Up或Up (healthy)。harbor-db和harbor-core有 healthcheck需要等几十秒。如果harbor-core一直 unhealthy先看日志# 查看 core 日志 docker compose logs --tail100 core # 查看 db 日志 docker compose logs --tail100 postgresql常见问题是 db 初始化失败原因多是data_volume目录权限不对或者之前跑过残留了旧数据。如果是全新环境可以把/data/harbor清空重来。3.3 首次登录与项目创建验证所有容器 healthy 后用浏览器或 curl 访问http://hostname。默认管理员账号是admin密码是harbor.yml里设置的harbor_admin_password。# 用 curl 验证 API 是否可用 curl -u admin:YourPassword http://hostname/api/v2.0/projects # 创建一个测试项目 curl -u admin:YourPassword -X POST http://hostname/api/v2.0/projects \ -H Content-Type: application/json \ -d {project_name:test-arm,public:true}如果 API 返回正常说明核心链路通了。接下来在另一台机器上配置 docker 客户端把 harbor 地址加入insecure-registries然后 push 一个 arm64 镜像测试。# 在客户端 /etc/docker/daemon.json 中加入 { insecure-registries: [hostname] } # 重启 docker 后登录 docker login hostname # 拉一个 arm64 的测试镜像并 push docker pull arm64v8/alpine:latest docker tag arm64v8/alpine:latest hostname/test-arm/alpine:latest docker push hostname/test-arm/alpine:latestpush 成功且能在 harbor 界面看到说明整个离线 arm 环境已经跑通。4. arm 离线安装 harbor 的避坑与排查5 个真实翻车记录4.1 镜像架构不匹配导致容器起不来现象docker compose up -d后harbor-core容器状态是Restarting日志里出现exec format error。原因加载的镜像实际是 amd64 架构在 arm64 内核上无法执行。这种情况通常发生在直接用了官方 amd64 offline 包或者从 x86 机器上导出的镜像。解决用docker inspect image --format {{.Architecture}}逐个检查把所有 amd64 镜像替换成 arm64 版本。最彻底的办法是在联网 arm64 机器上重新拉取并导出。4.2 prepare 阶段报找不到镜像现象执行./prepare时提示Error: image not found: goharbor/harbor-core:v2.9.0。原因prepare会检查本地是否有对应 tag 的镜像如果加载时 tag 被截断或版本号不一致就会报错。解决docker images确认实际 tag然后要么重新 tag要么修改harbor.yml里的harbor_version如果有这个字段。harbor 2.9 的prepare主要依赖 compose 文件里的 image 字段所以直接改docker-compose.yml里的 tag 也可以。4.3 数据目录权限导致 db 初始化失败现象harbor-db容器反复重启日志显示initdb: could not create directory ... Permission denied。原因data_volume指向的目录属主不是容器内 postgres 用户的 uid。harbor 的 db 容器以 uid 999 运行如果宿主机目录是 root 且权限 700就会失败。解决把数据目录权限放开或者直接 chown 成 999:999。生产环境建议用独立分区并设置合适权限。chown -R 999:999 /data/harbor/database4.4 nginx 端口冲突导致 80 或 443 起不来现象harbor-nginx容器启动后立刻退出日志显示bind() to 0.0.0.0:80 failed (98: Address already in use)。原因宿主机上已经有其他服务占用了 80 或 443比如系统自带的 web 服务或之前残留的容器。解决改harbor.yml里的http.port和https.port换成 8080、8443 等空闲端口重新./prepare并重启。注意改端口后客户端insecure-registries也要带端口。4.5 离线环境下 jobservice 无法连接 core现象镜像 push 成功但 harbor 界面里镜像扫描、复制等任务一直卡在 pendingharbor-jobservice日志报连接 core 超时。原因jobservice 通过内部网络访问 core如果 docker 网络配置有问题或者 core 的 healthcheck 没通过jobservice 会一直重试。解决先确认harbor-core是 healthy 状态然后检查docker network inspect harbor_harbor里各容器是否在同一网络。离线环境下如果之前手动改过网络配置容易出这个问题。最直接的办法是docker compose down后清空/data/harbor重新来一遍。5. 让 arm 离线 harbor 真正可用的几个进阶技巧跑通只是第一步真正要在生产用还得解决证书、存储和升级三个问题。先说证书内网环境虽然可以用 http但 docker 客户端默认要求 https配insecure-registries只是绕过长期看还是自签一套证书更稳。用 openssl 生成 CA 和服务器证书把 CA 放到客户端的/etc/docker/certs.d/hostname/ca.crtharbor.yml 里配好https.certificate和https.private_key重新 prepare 即可。注意证书的 SAN 要包含 hostname 的 IP 或域名否则 docker 会报证书不匹配。存储方面arm 服务器通常本地盘有限registry 数据增长很快。可以在harbor.yml里把data_volume指向大容量挂载点或者用 harbor 的存储后端配置对接外部对象存储。但离线环境下对接外部存储需要额外网络策略建议先本地盘跑定期清理无用镜像。harbor 自带垃圾回收在界面里可以手动触发也可以配定时任务。升级是另一个容易忽略的点。harbor 2.9 到后续版本升级时db schema 会变离线环境下不能直接拉新镜像。正确做法是在联网 arm64 机器上拉好新版本镜像导出 tar传到离线机器加载然后停旧容器、备份数据、改harbor.yml里的版本号、执行./prepare和docker compose up -d。升级前一定要备份/data/harbor/database和 registry 数据后悔药不好买。最后说一个我自己的习惯每次在 arm 离线环境部署完我都会写一个check.sh把架构检查、镜像列表、容器状态、API 健康检查串起来下次换机器直接跑一遍省得重复踩坑。这个脚本不长但能省下大量排查时间。#!/bin/bash # check.sh - arm 离线 harbor 健康检查 set -e echo 架构 uname -m echo 镜像架构抽查 for img in $(docker images --format {{.Repository}}:{{.Tag}} | grep goharbor); do arch$(docker inspect $img --format {{.Architecture}}) echo $img - $arch done echo 容器状态 docker compose ps echo API 健康 curl -s -o /dev/null -w %{http_code} http://localhost/api/v2.0/health echo这个脚本跑完基本能判断环境是否正常。如果 API 返回 200容器全是 Up镜像架构全是 arm64那这套 harbor 就可以放心用了。希望帮到你。本文还有配套的精品资源点击获取