☰
ARM架构离线部署Harbor 2.4.0:从镜像准备到容器排错全攻略
2026/10/20 20:20:34 网站建设 项目流程

简介:面向 ARM 服务器与内网环境提供的 Harbor 2.4.0 离线部署资源包,专门解决无外网条件下容器镜像仓库难以安装的问题。压缩包内共 6 个文件,包括 2 个 shell 自动化脚本、1 个 Harbor 镜像离线压缩包、1 个 YAML 配置模板、1 个 LICENSE 许可文件和 1 个 prepare 预处理脚本,整体大小约 402MB。部署流程简洁:预先安装 Docker 与 Docker Compose 后,执行 install.sh 即可完成配置生成、镜像导入与服务拉起,无需手动干预多项底层参数。资源对 ARM 架构做了针对性适配,在国产化服务器、树莓派等设备上也能稳定运行,适用于企业私有镜像仓库搭建、离线交付、容器化改造等场景。目前已有 1576 人浏览学习,文件数量少但功能闭环完整,既能帮助入职团队快速上线 Harbor,也为后续运维提供了配置入口与合规许可依据。

1. 离线装 Harbor 2.4.0 不只是解压文件:ARM 镜像差异才是第一道坎

拿官方harbor-offline-installer-v2.4.0.tgz直接部署到 arm64 服务器上,install.sh一路绿灯跑完,等docker ps一看,core 容器反复重启——这是我在某交付现场踩到的第一坑。Harbor 2.4.0 离线安装的难点从来不在解压和改 yml,而在于 arm 架构下的镜像架构不匹配、docker compose 组件缺失、以及 prepare 阶段对配置文件的隐式要求。本文把从镜像准备、离线导入、配置修改到容器排错的全过程拆开讲,适合手里只有 arm64 机器、且网络环境受限的开发者照着复现。版本固定、步骤固定,跟着走一遍就能在纯内网环境把 Harbor 跑起来。

2. ARM 离线包准备:镜像清单、导出与导入全流程

Harbor 官方发布页会同时提供在线和离线安装包,但离线包里的harbor.v2.4.0.tar.gz是构建机上直接docker save出来的产物。这个 tar 包默认是 amd64 架构,拿到 arm64 上 load 能成功,跑起来就是反复重启。要在 ARM 环境做离线安装,必须自己按平台拉镜像、重新打成离线 bundle,再整体搬到目标机器。

2.1 为什么 arm64 必须自己拉镜像而不是直接用官方 offline 包

Harbor 官方镜像仓库里的大部分镜像本身是支持多架构的,manifest list 里同时包含 amd64 和 arm64 的层。但官方离线安装包里的镜像 tar 是单架构快照,docker save导出的是实际拉取下来的镜像层,不是 manifest list。也就是说,发布包在哪个架构的机器上构建,出来的 tar 就只带哪个架构的层。

docker load不会做架构转换,它只是把镜像层原样塞进本地 Docker。arm64 机器加载 amd64 镜像时会提示 “Loaded image” 成功,但容器运行时因为内核无法执行 x86 指令,直接报exec format error。如果安装脚本执行完才发现这个问题,前面所有步骤都得推倒重来。所以第一个动作就是:在能联网的机器上按linux/arm64平台拉取全量镜像,重新打成自己的安装包。很多团队把这个步骤固化到 CI 里,每次升级 Harbor 版本都重新生成一套 arm64 bundle。

2.2 在联网机器上按平台拉取镜像并导出

Harbor 2.4.0 的核心组件镜像包括 prepare、harbor-core、harbor-db、harbor-jobservice、harbor-portal、harbor-registryctl、registry-photon、nginx-photon、redis-photon,以及启用漏洞扫描时要用的 trivy-adapter-photon。下面这个脚本在一台能联网的机器上执行,目标机是 arm64 就用linux/arm64拉取,拉完直接打短 tag 再 save,省掉目标机上二次 tag 的麻烦。

#!/bin/bash # 在能联网的机器上执行,生成 arm64 架构的 Harbor 镜像离线包 PREFIX=your.registry.example.com/harbor # 换成你实际使用的镜像仓库前缀 TAG=v2.4.0 ARCH=linux/arm64 mkdir -p arm64_images images=( prepare harbor-core harbor-db harbor-jobservice harbor-portal harbor-registryctl registry-photon nginx-photon redis-photon trivy-adapter-photon ) for name in "${images[@]}"; do docker pull --platform "$ARCH" "$PREFIX/$name:$TAG" docker tag "$PREFIX/$name:$TAG" "$name:$TAG" docker save "$name:$TAG" -o "arm64_images/$name.tar" done

脚本里先显式指定--platform linux/arm64,确保 Docker 从 manifest list 里挑 arm64 的层,而不是按当前机器的架构拉取。之后打短 tag 是因为 Harbor 的prepare脚本和最终生成的docker-compose.yml里引用的镜像是harbor-core:v2.4.0这类短名,不提前打短 tag,目标机 load 后镜像会带着仓库前缀,install.sh 找不到镜像。

参数方面,PREFIX根据你实际拉取源填,如果官方仓库访问不稳定,可以先同步到内网镜像仓库再从这里拉;TAG固定 v2.4.0,不建议跨版本混用,Harbor 各组件镜像 tag 必须对齐同一个版本,混 tag 会出现 core 和 jobservice 之间 API 不兼容。列表里没放 notary-server 和 notary-signer,因为默认install.sh不启用 notary,如果后续要做镜像签名,需要把这两个镜像也加进列表重新生成。

2.3 离线导入到目标机器:load 与 tag 的顺序问题

把arm64_images目录拷到目标机后,导入命令很简单,但要验证架构。下面这段代码在目标机上执行,循环导入所有 tar,再用image inspect确认架构字段。

cd arm64_images # 逐个导入,save 时用了短名,load 后镜像名就是 name:tag for f in *.tar; do docker load -i "$f" done # 验证架构,必须输出 arm64 docker image inspect harbor-core:v2.4.0 --format '{{.Architecture}}'

docker load会打印 “Loaded image: harbor-core:v2.4.0”,因为我们在联网机上 save 前已经重新 tag 过,所以目标机上不需要再执行docker tag。如果架构验证输出不是 arm64,说明拉取时--platform参数没生效,或者源仓库里根本没有 arm64 的 manifest,需要回到联网机上确认拉取的镜像层。

这里还有个小细节:不要把所有 tar 打成一个大的 tar 再拷,一旦传输中断整个文件作废。保持每镜像一个 tar,传输工具可以做断点续传,报错时也能定位到具体是哪个镜像损坏。

3. 系统侧准备:Docker、Docker Compose 与依赖安装顺序

镜像就绪后,目标机的容器运行时环境是下一个关口。Harbor 的 install.sh 依赖完整的 Docker Engine 和 docker-compose 命令,缺一个都跑不起来。ARM 服务器上常见的坑是厂商预装了老版本 Docker,或者只有 podman 没有标准的 docker compose,导致安装脚本卡在环境检查阶段。

3.1 适配 ARM 的 Docker 版本选型

arm64 架构下 Docker 的版本选择直接影响 Harbor 的稳定性。19.03 版本能跑容器,但对多架构 manifest 的处理不完善,docker pull --platform参数在部分场景下会失效;20.10 之后 Docker 默认启用 manifest 支持,--platform行为稳定,离线导入导出也更可靠。建议直接用 20.10 及以上版本,不要为了兼容老系统去选低版本。

另一个容易被忽略的点是 containerd 和 runc 的配套关系。Docker 20.10 依赖 containerd 1.4 以上,如果系统里残留旧版 containerd,docker info可能正常,但容器启动时会在 runc 阶段报错。稳妥的做法是把旧版本彻底清掉,再按 containerd、docker-ce-cli、docker-ce 的顺序统一安装。

3.2 离线环境下的 Docker 组件安装

在联网机器上下载 arm64 架构的 deb 包,拷到目标机后用apt install -y ./xxx.deb安装。注意 deb 包必须选 arm64 版本,在 x86 机器上下载的包拷到 ARM 机器上会直接报 wrong architecture。

# 在目标机执行,三个包都放到当前目录 sudo apt install -y ./containerd.io_1.6.*.deb \ ./docker-ce-cli_20.10.*.deb \ ./docker-ce_20.10.*.deb sudo systemctl enable --now docker # 验证 client 和 server 两段都正常输出 docker version

安装顺序不能乱:containerd 是 docker-ce 的底层依赖,必须先装;docker-ce-cli 提供 docker 命令行工具;docker-ce 是核心引擎。systemctl enable --now docker把 Docker 设为开机自启并立刻启动。验证时docker version会分 client 和 server 两段输出,如果只看到 client 段没有 server 段,说明 daemon 没起来,查systemctl status docker。

3.3 docker-compose 的安装方法与版本坑

Harbor 2.4.0 的 install.sh 对 compose 的检测逻辑比较保守:优先找docker-compose命令,找不到才会尝试docker compose子命令。如果目标机上只装了新版 Docker 的 compose 插件,脚本可能停在环境检查阶段,而不是直接跑到镜像加载。最省事的做法是离线拷贝一个 aarch64 的 docker-compose 二进制到/usr/local/bin。

# 把在联网机器上下载的 docker-compose-linux-aarch64 拷到目标机 sudo mv docker-compose-linux-aarch64 /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose # 验证版本,1.29.x 和 2.x 都兼容 Harbor 2.4.0 docker-compose version

这个二进制是在 x86 机器上下的,但文件名里明确标注了 aarch64,不要混用。装完后建议同时确认docker compose version也可用,因为后续手动维护容器时,两个命令风格不一样。docker-compose 1.29 和 2.x 在 Harbor 2.4.0 下都能正常工作,关键是命令要能找到,版本上没有必要追求最新。

4. 正式安装 Harbor 2.4.0:harbor.yml 配置与 install.sh 执行逻辑

镜像和容器运行时都准备好之后,正式安装反而只是解压、改配置、跑脚本三个动作。但配置文件的几个隐式要求会把不少人卡在 prepare 阶段,尤其是 https 证书和 hostname 这两项,必须在执行安装前处理好。

4.1 harbor.yml 关键配置项解读

解压harbor-offline-installer-v2.4.0.tgz后,先把harbor.yml.tmpl复制成harbor.yml,再做最小修改。下面是内网部署时最常用的一段配置,hostname 填目标机的内网 IP,https 整个注释掉,密码和数据库口令改成自己的。

hostname: 192.168.10.21 http: port: 80 # https: # port: 443 # certificate: /data/cert/server.crt # private_key: /data/cert/server.key harbor_admin_password: Harbor12345 database: password: root123 max_idle_conns: 100 max_open_conns: 900 data_volume: /data/harbor trivy: ignore_unfixed: false skip_update: true insecure: false

hostname不要写 localhost 或 127.0.0.1,后面docker login和 Web 访问都要用这个地址解析服务,写 localhost 会导致外部客户端无法访问。https段在首次部署时直接注释干净,不注释的话 prepare 阶段会去读证书文件,证书路径不存在直接报错退出。data_volume建议放到独立挂载盘,Harbor 的数据库、镜像存储、redis 数据都在这下面,系统盘空间不够会引发后续一系列问题。trivy.skip_update在离线环境必须设成 true,否则漏洞扫描服务启动后会尝试联网更新漏洞库,然后卡死在启动阶段。

4.2 install.sh 的执行流程与常见报错

配置改好后执行安装命令,这里选择了开启 trivy,因为镜像列表里已经包含了 trivy-adapter 镜像。

sudo ./install.sh --with-trivy

install.sh 的执行流程分四段:先检查 docker 和 docker-compose 可用性;再加载官方离线包里的镜像,如果镜像已经 load 过会提示 already exists;接着运行 prepare 脚本,读取 harbor.yml 生成 docker-compose.yml 和一系列配置目录;最后用 compose 把全部容器拉起。加--with-trivy才会启动漏洞扫描容器,不加的话 harbor.yml 里 trivy 段会被忽略。

脚本跑完看到 “Harbor has been deployed and is running” 才算成功。如果中途失败,先看是停在哪一步:环境检查失败说明 docker 或 compose 有问题;镜像加载阶段失败说明 tar 包损坏;prepare 阶段失败基本是 harbor.yml 配置问题;最后容器拉起失败要看docker compose ps和容器日志。

4.3 安装后的目录结构与日志位置

安装完成后data_volume下会出现 database、secret、redis、registry 等子目录,分别对应 PostgreSQL 数据、Harbor 密钥、缓存数据和镜像存储。排查问题时先看服务状态,再看具体容器日志。

cd /app/harbor # 解压安装包的目录 docker compose ps # 查看核心服务日志,容器名以 harbor- 开头 docker logs harbor-core --tail 50

docker compose ps会列出所有服务和健康状态,正常情况下 8 个核心容器都是 running 状态,可选服务看安装参数。harbor-core 是所有请求的入口,它的日志里如果出现数据库连接失败,优先检查 database 容器状态和harbor.yml里的数据库密码是否一致。

5. 避坑记录:ARM 离线安装 Harbor 的五个典型事故

离线环境下出问题的特点就是报错信息往往模棱两可,需要结合环境特征去推断原因。这五条是我实际踩过、以及身边同事反复遇到的坑,每条都按现象、原因、解决三个维度拆开。

5.1 现象:install.sh 执行完容器反复重启,core 和 jobservice 起不来

装完看docker ps,core、jobservice 这几个容器一直显示 Restarting,docker logs里只有一句exec format error。原因是镜像架构不对——要么直接用了官方 amd64 离线包,要么拉镜像时没带--platform linux/arm64。docker load不校验架构,所以导入阶段毫无提示。解决方法是登录目标机执行docker image inspect harbor-core:v2.4.0 --format '{{.Architecture}}',如果输出不是 amd64 就删除旧镜像,按 2.2 节重新生成离线包再导入一次。

5.2 现象:install.sh 报 docker-compose not found,卡在环境检查

脚本开头就退出,提示找不到 docker-compose。原因是目标机只装了 docker 引擎,或者只有新版 compose 插件但命令行里没有docker-compose这个可执行文件。Harbor 2.4.0 的脚本对 compose v2 的支持不完整,优先找的还是独立二进制。解决方法是离线拷贝docker-compose-linux-aarch64到/usr/local/bin/docker-compose并加执行权限,然后重新跑 install.sh,不需要动 docker 引擎本身。

5.3 现象:prepare 阶段报证书文件不存在的错误

日志里出现certificate /data/cert/server.crt not found,安装直接中断。原因是harbor.yml里 https 段没有注释,prepare 会去读配置里指定的证书路径,文件不存在就报错。解决方法是把 https 段全部注释掉,用 http 端口跑内网部署,等有正式证书再补配。还有一个小坑:不能只注释 certificate 行而保留 https 段,prepare 会把https.enabled判为 true。

5.4 现象:容器全部 running,但 Web 页面打不开

docker compose ps显示所有容器都是 running,健康检查也正常,但浏览器访问 IP 就是不通。原因通常是 hostname 配置问题或端口被占。如果 hostname 写的是 localhost,Harbor 生成的 nginx 配置只监听 localhost,外部请求进不来;如果 80 端口被其他服务占用,容器会启动失败但状态偶尔显示 running。解决方法是把 hostname 改成内网固定 IP,http.port改成 8080,访问和docker login都带上端口号。排查时先执行ss -tlnp | grep 80确认端口占用情况。

5.5 现象:harbor-db 启动失败,日志提示数据目录权限错误

数据库容器起不来,日志里出现data directory has wrong ownership。原因是data_volume目录属主不对,容器内部运行用户无法写入数据目录。解决方法是执行chown -R 10000:10000 /data/harbor,这是 Harbor 镜像内部运行用户常用的 uid 映射。如果问题依旧,检查数据目录所在磁盘的 inode 是否耗尽,数据库文件多,小分区很快会被 inode 占满,df -i看一下剩余值。

6. 安装后的验证与备份:给离线环境留条后悔药

服务跑起来之后,先用 API 做一轮快速验证,确认 core、数据库、redis 这些组件是真的正常,而不是容器活着但业务不可用。Harbor 2.4.0 原生支持 API v2.0,健康检查和登录验证两条命令就够了。

# 健康检查,期望返回 {"status":"healthy"} curl -s http://192.168.10.21/api/v2.0/health # 带基本认证请求项目列表,返回 200 说明 core 和数据库正常 curl -s -u admin:Harbor12345 "http://192.168.10.21/api/v2.0/projects?page_size=10"

健康检查通过后再验证镜像上传:用docker login 192.168.10.21登录,push 一个测试镜像到项目里,再 pull 回来,走完这一步整个链路才算验证完整。

离线环境的备份比在线环境更重要,因为出问题后没有快速恢复手段,只能靠备份兜底。备份的核心是data_volume下的 database、secret、redis 三个目录,secret 一旦丢失,所有已存镜像的访问凭证和密码都会失效。备份前先停服务,保证 PostgreSQL 数据落盘一致。

cd /app/harbor docker compose down cd /data tar czf harbor-backup-$(date +%Y%m%d).tar.gz harbor/database harbor/secret harbor/redis # 重新拉起服务 cd /app/harbor docker compose up -d

恢复时解压 tar 到原路径,再执行docker compose up -d即可。这套备份流程我在多台 arm64 服务器上验证过,每次升级或迁移前强制走一遍。有次同事在另一台机器上恢复,因为少备份了 secret 目录,所有已存项目的 robot 账号全部失效,只能让各团队重新生成凭证。从那以后我每次装完 Harbor 都先把这三个目录 tar 一遍,再开始传镜像,这个习惯救过我好几次。希望帮到你,少走点离线环境的弯路。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询