简介:面向ARM64架构的Harbor离线部署包,版本为当前最新的v2.13.1,专供在鲲鹏、飞腾等ARM处理器服务器上搭建镜像仓库使用,尤其适合Kubernetes与Docker离线环境下的运维场景。压缩包以tgz格式封装,共6个文件,包含2个shell脚本(负责安装与配置处理)、1个镜像tar.gz文件(内含Harbor本体镜像),以及license、prepare工具和配置模板,整体大小679.05MB。资源下载后可直接执行安装脚本完成部署,无需在线拉取大量容器镜像,适合内网隔离或网络受限的机房环境;通过附带的prepare和yml模板可灵活调整存储、TLS及认证参数。该资源已持续更新至v2.13.1,浏览学习人数已有526人,对于需要在ARM64平台上快速上线Harbor的运维或开发人员来说,是一份省时省力的工具包。
1. 拿到 ARM64 服务器,Harbor v2.13.1 离线安装包先别急着装
拿到一台飞腾或鲲鹏的 ARM64 服务器,系统是麒麟 V10 或 CentOS 7,下一步要在内网部署 Harbor v2.13.1。别急着从网上随便找一个“ARM64 版离线安装包”就装,我在这里翻过不只一次车:下载的 tgz 解压后,docker load 时提示 manifest 不匹配;或者镜像加载成功,容器一启动就报 exec format error。Harbor 的离线安装包不是源码包,它本质上是“预打包的 Docker 镜像 + 安装脚本”,镜像架构决定这个包能不能在当前主机直接跑。这篇笔记从离线包的拆解、ARM64 离线包的自制、内网 install.sh 完整落地,到常见排错,按一条可复现的流程讲完。适合负责内网镜像仓库交付、帮机房做离线部署的人,照着走能直接复现。
2. 拆解 Harbor v2.13.1 离线包:镜像架构、文件组成和识别方法
安装包文件名按版本号来,常见的是harbor-offline-installer-v2.13.1.tgz,单看文件名很难直接分辨 amd64 还是 arm64。真正决定架构的是包内那个镜像压缩包。先把离线包的组成和架构判断方法说清楚,后面做 ARM64 版才有依据。
2.1 离线安装包解开后,核心其实是一个镜像归档
把官方离线包解压,进入harbor目录,关键文件是可预期的:install.sh负责安装,prepare负责根据harbor.yml生成 compose 配置,harbor.yml.tmpl是配置模板,common.sh是脚本公共函数。这里最值得注意的文件是harbor.v2.13.1.tar.gz,它是用docker save导出的全部 Harbor 镜像归档。
tar -xzf harbor-offline-installer-v2.13.1.tgz cd harbor ls -lh我通常先看这个列表,再判断离线包完成度。一个合格的离线包不需要网络,install.sh会先把harbor.v2.13.1.tar.gz用docker load加载进本地,再由docker compose up启动。所以只要这个镜像归档的架构和当前主机不匹配,后面全部白搭。
看一个离线包是不是能直接用,第一件事不是改配置,而是查镜像归档里的架构字段。docker save出来的 tar 内部有manifest.json和每层镜像的 config 文件,config 文件里的architecture字段会明确写amd64还是arm64。文件内部结构大概是:manifest.json、若干layer.tar或blobs/sha256/...、还有一份记录镜像和 tag 对应关系的repositories。这些信息在安装失败时是排查的第一线索。
2.2 ARM64 和 x64 的镜像差异,为什么绕不过去
ARM64 和 x64 的差异不是改个文件名就能解决的。Harbor 的容器镜像里,harbor-core、harbor-jobservice是 Go 编译的二进制,harbor-portal是 Nginx 加静态文件,harbor-db是 PostgreSQL,基础镜像各自对应官方平台版本。x86 指令集编译出来的二进制在 ARM64 内核上无法执行,反过来也一样。就算docker load把镜像加载成功,容器起来时也会因为缺exec format error或exec user process caused: exec format error而退出。
在 ARM64 v8a 上部署,还有一个容易忽略的点:ARM64 下存在 v8.0、v8.1、v8.2 等微架构差异,大部分商用镜像都按linux/arm64/v8或更低的兼容级别打包,飞腾、鲲鹏这类处理器通常能兼容运行 v8.0 基础镜像。所以看到arm64/v8直接采用即可,不必为某颗具体芯片型号单独找安装包。
很多“伪 ARM64 离线包”的问题也出在这:有的人只是把 amd64 的镜像 tar 原样改了个名,或者在 x86 机器上没有经过docker buildx --platform linux/arm64构建就重新打了一个压缩包。这种包在 ARM64 机器上要么加载报错,要么运行时报格式错误。判断标准只有一个:镜像或镜像归档里的实际 platform 字段,而不是文件名带了什么后缀。
2.3 一分钟内定位离线包架构的检查手段
在目标 ARM64 机器上原地验证最直接。先docker load,再对任意一个 Harbor 镜像做inspect,看看 Architecture 字段是不是 arm64。
docker load -i harbor.v2.13.1.tar.gz docker image inspect goharbor/harbor-core:v2.13.1 --format '{{.Os}}/{{.Architecture}}'输出如果出现linux/arm64,说明镜像归档确实是 ARM64 可用;如果显示linux/amd64,这个离线包在当前 ARM64 机器上是起不来容器的。还有人习惯用docker run --rm goharbor/harbor-core:v2.13.1 true做冒烟测试,如果直接报exec format error,基本可以确认架构不匹配。这个方法在拿到任何第三方离线包时都适用,不用等整个安装流程跑完才后悔药。
3. 制作并安装 Harbor v2.13.1 的 ARM64 版离线包:从导出镜像到 install.sh 跑通
如果官方或第三方给的离线包架构不对,最常见的做法不是等别人重新发布,而是自己拿一台能联网的 ARM64 机器重新导出镜像,再替换到离线包里。这套流程我至少走了三遍,把步骤固定下来能省很多时间。
3.1 准备一台能联网的 ARM64 机器,或者用 QEMU 模拟 arm64 环境
先决条件是有 Docker 服务,并且这台机器能访问 Harbor 镜像仓库的源站。常见做法是在临时的一台 ARM64 云主机或飞腾开发板上完成导出,再把产物拷贝到内网。没有 ARM64 实体机时,用 QEMU 模拟 arm64 也成立:宿主 x86 机器上装qemu-user-static,配合 Docker 的 binfmt 机制,pull 时指定--platform linux/arm64/v8,一样能把 ARM64 镜像拉到本地归档。
我一般更推荐直接找一台真实 ARM64 机器,而不是长期依赖 QEMU。原因很简单:Harbor 安装过程里容器涉及网络、存储、systemd 资源限制,QEMU 下的运行表现和物理 ARM64 机器有差异,特别是权限和 sysctl 相关的错误,只有真机才能暴露。
3.2 拉齐 Harbor 镜像清单并导出 ARM64 镜像归档
Harbor v2.13.1 安装涉及的镜像包括 core、jobservice、portal、registry、registryctl、db、log、nginx、redis、trivy 等。先在一台 ARM64 机器上配置好 Docker,逐个 pull,再统一用docker save导出一个归档文件。
IMAGE_LIST="goharbor/harbor-core:v2.13.1 \ goharbor/harbor-jobservice:v2.13.1 \ goharbor/harbor-portal:v2.13.1 \ goharbor/harbor-registry:v2.13.1 \ goharbor/harbor-registryctl:v2.13.1 \ goharbor/harbor-db:v2.13.1 \ goharbor/harbor-log:v2.13.1 \ goharbor/nginx-photon:v2.13.1 \ goharbor/redis-photon:v2.13.1" docker pull goharbor/harbor-core:v2.13.1 docker image inspect goharbor/harbor-core:v2.13.1 --format '{{.Architecture}}/{{.Os}}' | grep arm64 docker save $IMAGE_LIST | gzip > harbor.v2.13.1.arm64.tar.gz这段命令里,docker pull会按当前机器的架构拉取,ARM64 机器上拉到的就是 arm64 镜像。docker image inspect用 Go 模板只输出os/architecture,用来确认拉出来的确实是 arm64。最后docker save把镜像归档成单个 tar 流,再 gzip 压缩,避免内网拷贝时占用太多空间。如果你的镜像源不是默认仓库,需要提前做好 registry mirror 或直连源站的网络配置,否则在 ARM64 机器上拉镜像也会卡在第一步。
在这之后,要把官方离线包里的原镜像归档替换掉。官方离线包里的harbor.v2.13.1.tar.gz如果确认是 amd64 的,先备份,再把新导出的归档改成同名文件。
cd harbor mv harbor.v2.13.1.tar.gz harbor.v2.13.1.tar.gz.amd64.bak cp ../harbor.v2.13.1.arm64.tar.gz ./harbor.v2.13.1.tar.gzinstall.sh调用时并不校验内容是否来自官方,只认文件名是否存在。替换完成后,这个离线包就成了真正可用的 ARM64 版。需要提醒一点:tar 文件体积通常不小,建议在拷到内网前先算一次 sha256,和目标机上的文件做比对,避免传输中断造成归档损坏。
3.3 按内网场景修改 harbor.yml:hostname、存储与端口
离线替换做完,接着改harbor.yml。官方包解压后自带harbor.yml.tmpl,先复制成harbor.yml。核心配置项有三个:hostname、http/https、data_volume。
cp harbor.yml.tmpl harbor.yml典型的内网最小配置长这样:
hostname: 192.168.10.20 http: port: 80 https: port: 443 certificate: /data/cert/harbor.crt private_key: /data/cert/harbor.key data_volume: /data/harbor log: level: info database: password: ChangeMe123参数说明:hostname必须是客户端能访问到的地址,不能写 localhost,否则其他机器docker login会失败;内网没有 DNS 时直接用管理 IP 最省事。http.port建议保留 80,Harbor 的prepare脚本会对 hostname 和端口生成对应的docker-compose.yml。https默认是打开的,生产环境建议用自签证书;如果前期只想在隔离网络里跑通,可以把https整段注释掉,后面再补证书也来得及。data_volume是镜像存储目录,务必预留出比离线包本身大三倍以上的磁盘空间,Harbor 的 registry 存储层和数据库都会写在这里。
改完配置,下一步就交给install.sh。它内部先跑prepare生成 compose 文件,再docker load加载替换后的镜像归档,最后启动全部容器。离线环境里可以先把外部组件关掉,比如./install.sh --with-trivy这种参数,在没有外网、无法更新漏洞数据库的阶段,先不启用更稳妥。
3.4 跑 install.sh 并验证三个关键状态
执行安装需要 root 权限,或者把当前用户加入 docker 组。直接跑:
sudo ./install.sh脚本输出的最后一行如果出现类似Harbor has been installed and started successfully的内容,说明安装主体完成。只看到这行还不够,我用三条命令做启动验证:
docker compose ps curl -k https://192.168.10.20/api/v2.0/health docker login 192.168.10.20 -u admin -p Harbor12345docker compose ps看所有容器是不是处于 Up 状态;curl打/api/v2.0/health,返回{"status":"healthy"}才算服务就绪;docker login是镜像上传前的最后一道验证,登录成功了,说明 registry、portal、db、nginx 这一整条链路是通的。
第一次启动后,还可以把install.sh的日志留底,后续排查容器重启问题时省得反复翻docker logs。ARM64 环境里docker-compose.yml由prepare生成,镜像 tag 固定跟随 v2.13.1,如果出现某个容器反复 Restarting,多半还是镜像架构或存储权限问题,这一块放到下一章专门说。
4. ARM64 离线部署 Harbor 的五个硬坑:现象、原因和解决办法
过程中踩过的坑基本可以分成长这样五类,每一条都按“现象 → 原因 → 解决”的顺序拆开,方便后面照着排查。
4.1 docker load 时报 “no matching manifest for linux/arm64”
现象:在 ARM64 机器上执行docker load -i harbor.v2.13.1.tar.gz,Docker 直接报no matching manifest for linux/arm64 in the manifest list entries。
原因:镜像归档是 amd64 的 manifest,Docker 尝试解出当前平台的镜像实例,找不到 arm64 的匹配项。这个问题在替换前最容易发生,原因是网上很多人下载的“ARM64 版”实际是把官方 amd64 离线包改名重新打包,没有真正替换过镜像归档。
解决:不要在这里做任何绕过,老老实实按第 3.2 节的方式导出 arm64 镜像归档再替换。如果改文件名的思路已经进行到一半,可以用docker manifest inspect goharbor/harbor-core:v2.13.1查看远端镜像的 platform 列表,确认arm64/v8存在,然后重新在 ARM64 机器上 pull 和 save。
4.2 install.sh 卡在拉取镜像,而不是使用本地离线归档
现象:sudo ./install.sh执行到一半,日志显示Pulling goharbor/harbor-core:v2.13.1,内网环境里网络不通就一直卡在那。
原因:install.sh加载离线包后,docker compose up如果发现某个镜像在本地不存在,Compose 会退到默认行为:去远程仓库拉取。这通常意味着docker load阶段没有真正加载成功,最常见的是harbor.v2.13.1.tar.gz文件名不对,或者docker load因为磁盘空间不足而中止。
解决:先看 install.sh 前面几行日志,确认docker load是否出现Loaded image的输出。没有输出,就手动执行docker load -i harbor.v2.13.1.tar.gz看完整报错。空间不足时df -h会看到根分区或 docker>setenforce 0 sudo ./install.sh
如果生产环境不能关 SELinux,更精细的做法是把data_volume、日志目录放到固定路径,再用chcon -R -t container_file_t /data/harbor设置正确的上下文。也可以在所有容器启动前创建一个/data/harbor目录,并写成属主属组都是 10000,很多 Harbor 容器进程是以 UID 10000 运行的,这是我在踩坑后才检查到的位置。
4.4 数据目录容量判断偏差,离线包解压半路中断
现象:docker load执行到一半中断,报no space left on device,或者磁盘明明够,但install.sh生成的日志目录写入失败。
原因:离线包harbor.v2.13.1.tar.gz看着只有 1GB 多,但这是 gzip 压缩后的体积,docker load解压后占用接近原始层体积,通常翻倍。再加上data_volume里 registry 的存储目录又需要一份空间,很多人只按压缩包体积规划磁盘,装上才发现不够。
解决:规划容量时按离线包解压后的 3 倍预留。检查时不要只盯一个分区,/、/var/lib/docker、/data可能是三个不同分区。docker info | grep 'Docker Root Dir'可以看到 docker>{ "insecure-registries": ["192.168.10.20"] }
然后重启 docker。完整操作顺序是:先修改daemon.json,执行systemctl restart docker,再docker login 192.168.10.20。生产环境不要一直用 insecure 模式,正确做法是自建 CA,把 CA 证书分发给客户端,并在daemon.json里指向私有 registry 地址和证书。ARM64 的客户端机器同样可以在/etc/docker/certs.d/192.168.10.20/下放ca.crt,Docker 会自动信任,这对内网大量 ARM64 客户端分批配置时更可控。
5. 落地前最后一道工序:验证 ARM64 镜像清单并按批导入业务镜像
安装成功只是第一步,真正的交付还要把业务镜像送进 Harbor。我习惯在部署前先验证镜像源是否真的支持 ARM64,然后才安排批量导入。
5.1 用 docker buildx imagetools 在离线前核对所有平台
在能联网的机器上,用docker buildx imagetools inspect检查远端镜像的 platform 列表,比直接 pull 更省流量。
docker buildx imagetools inspect goharbor/harbor-core:v2.13.1输出里的Platforms字段会列出linux/arm64/v8、linux/amd64等。这一步能在离线操作前就把“这个镜像支不支持 ARM64 机器”的黑匣子打开,避免拉到不带 arm64 的镜像后才发现。对于业务系统镜像,同样可以用这个命令验一遍,特别是那些基础镜像是 alpine 或 debian 的,一般都有多架构支持,但一旦基础镜像是第三方定制的 x86-only 二进制,就得联系上游重新提供。
5.2 在目标机上批量 load 业务镜像并推入 Harbor
离线业务镜像通常也是用docker save导出的。在 ARM64 目标机上加载一套镜像,再推入 Harbor,命令如下:
docker load -i business-images.tar.gz docker tag my-app:arm64-v1.0 192.168.10.20/library/my-app:arm64-v1.0 docker push 192.168.10.20/library/my-app:arm64-v1.0参数说明:docker load会原样还原 save 时的 image tag;docker tag在本地给镜像增加一个带 Harbor 地址的 tag,推送时 Docker 才知道要去哪个 registry;docker push前确保已经用 admin 账号或新建的项目账号做过docker login。这里有个细节,离线导入的镜像如果架构不对,docker load不会报错,要等docker run才会暴露,所以我建议推之前先docker image inspect my-app:arm64-v1.0 --format '{{.Architecture}}'确认一次。
5.3 一张部署检查表和我的固定动作
| 检查项 | 验证结果 |
|---|---|
| 离线包镜像归档架构 | docker image inspect输出linux/arm64 |
| install.sh 完成后容器状态 | docker compose ps全部 Up |
| Harbor API 健康 | curl /api/v2.0/health返回 healthy |
| 磁盘空间 | style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />
|