Harbor v2.4.0 ARM离线安装实战:从镜像架构到避坑指南

发布时间:2026/10/11 2:29:47
Harbor v2.4.0 ARM离线安装实战:从镜像架构到避坑指南
简介面向 ARM 架构服务器的 Harbor v2.4.0 离线安装包专为无外网或内网隔离环境下的容器镜像仓库部署而准备适合需要快速搭建企业级 Harbor 的运维人员与开发者尤其适配国产化芯片平台。zip 压缩包内共 6 个文件涵盖一键安装脚本sh、配置模板yml、镜像离线包gz、许可证与预处理辅助脚本等组件整包约 402.34MB使用前需预先装好 Docker 与 Docker Compose。已有 1574 人学习或下载适合作为 ARM 环境部署参考。资源价值在于提供一套开箱即用的 ARM 离线安装方案安装脚本封装依赖检查与启动流程配置文件预置常用参数离线镜像包避免从外网拉取失败可批量交付到多台设备也可作为企业内网镜像仓库的基础模板。1. 离线安装包拿对了却在 ARM 服务器上起不来先把问题对准假设你和我一样在某国产 ARM 服务器上部署 Harbor v2.4.0下载了官方推荐的离线安装包 harbor-offline-installer-v2.4.0.tgz解压后直接./install.sh等了五分钟docker ps一看registry 和 core 容器反复重启日志里清一色exec format error。这不是操作问题而是架构问题——官方离线包里的所有镜像都是 amd64 版本ARM 的 CPU 根本执行不了。Harbor v2.4.0 离线安装ARM 架构的真实路径是先把镜像架构换成 arm64再做离线导入和安装。本篇按我实际走通的方案从架构判断、镜像准备、配置修改到踩坑排查一步步讲清楚。2. 为什么 ARM 上不能直接用官方离线包镜像架构与两条可行路线2.1 Harbor v2.4.0 的组件构成与镜像架构标识Harbor 不是单个二进制而是一组容器编排起来的服务。v2.4.0 的 docker-compose 里大致包含以下组件组件镜像名tag v2.4.0职责核心服务goharbor/harbor-coreAPI、认证、权限控制镜像存储goharbor/registry-photon基于 Docker Registry 的存储数据库goharbor/harbor-dbPostgreSQL保存元数据缓存goharbor/redis-photonRedis会话与任务缓存前端goharbor/harbor-portalWeb UI任务调度goharbor/harbor-jobservice复制、清理、扫描任务网关goharbor/harbor-nginx反向代理与 TLS 终结漏洞扫描goharbor/trivy-adapter按需扫描镜像漏洞日志goharbor/harbor-log统一日志收集每个镜像在 Docker Hub 上都是一个多架构 manifest同一个 tag 下可以同时有 linux/amd64 和 linux/arm64 的变体。arm64 服务器执行docker pull goharbor/harbor-core:v2.4.0时Docker 会自动选择 arm64 变体但官方离线包里的harbor.v2.4.0.tar.gz是在 x86 环境打包的里面的镜像全是 amd64ARM 服务器 load 进去能识别跑起来就会崩。2.2 官方离线包为什么在 ARM 上翻车install.sh的核心逻辑就三步加载harbor.v2.4.0.tar.gz里的镜像、用prepare容器生成配置、docker compose up -d启动。问题出在第一步加载进来的镜像没有一个能在 arm64 内核上运行。容器启动时内核执行 ELF 格式的二进制amd64 的指令集在 arm64 上直接抛exec format error表现出来就是容器无限 restart。这一点在官方文档里其实有说明离线安装包面向 amd64 环境提供ARM 部署应使用在线安装包或自行准备镜像。但在完全离线的内网在线安装包形同虚设所以必须走“自行准备 arm64 镜像”这条路。2.3 两条路线怎么选直连拉取 vs 摆渡机中转根据目标机器能不能临时访问外网我一般会分两种情况路线条件操作路径适用场景路线 A目标机直连拉取安装机能访问 Docker Hub在目标机上直接 pull 所有 arm64 镜像save 后 load 给 install.sh 用有外网窗口图省事路线 B摆渡机中转目标机完全离线另有一台可联网的 arm64 机器在摆渡机上 pull save 成 tar拷贝进内网load 后安装内网隔离、涉密环境注意摆渡机也必须是 arm64。你不能在 x86 机器上 pull 然后指望 save 出 arm64 镜像——docker pull是按当前机器架构取变体的x86 机器拉下来的就是 amd64。2.4 先确认目标机架构与 Docker 环境动手前先确认三件事CPU 架构、Docker 版本、Compose 是否可用。我常用下面这套命令# 查看 CPU 架构确认是 aarch64 uname -m # 查看 docker 版本与服务状态 docker version --format {{.Server.Version}} systemctl status docker | head -5 # 确认 compose 插件是否存在v2 和 v1 至少有一个 docker compose version || docker-compose versionuname -m输出aarch64就说明是 64 位 ARM。Docker 版本建议 20.10 以上Harbor v2.4.0 对 docker engine 的要求并不高但老版本在处理多架构 manifest 时偶尔有兼容问题升级到 20.10 能少踩坑。Compose 这一步务必在安装前确认离线机经常只装了 docker 没装 compose后面install.sh会直接失败。3. 离线安装包准备与 harbor.yml 配置先把配置改对再谈镜像3.1 下载并解压离线安装包确认目录结构离线安装包从官方 Release 页面下载文件名一般是harbor-offline-installer-v2.4.0.tgz大约几百 MB里面带了一个harbor.v2.4.0.tar.gz镜像包。在任意一台机器上解压后先看结构mkdir -p /opt/harbor tar -zxvf harbor-offline-installer-v2.4.0.tgz -C /opt/harbor cd /opt/harbor ls -lh目录下会看到install.sh、harbor.yml.tmpl、docker-compose.yml、harbor.v2.4.0.tar.gz、common.sh等文件。harbor.yml.tmpl是配置模板第一次安装要先复制成harbor.yml再改。这里的docker-compose.yml是模板生成后的产物里面每个服务的image字段就是后面要准备镜像清单的来源先记住这一点第 4 章的批量拉取脚本会用到。3.2 harbor.yml 关键配置项hostname、密码、数据目录复制模板后我一般只改必改的几项其余保持默认cp harbor.yml.tmpl harbor.yml vim harbor.yml关键的配置项如下# 对外提供服务的地址必须改成客户端能访问的 IP 或域名 hostname: 192.168.10.20 # HTTP 方式v2.4.0 默认关闭 HTTPS离线内网不建议开证书会拖垮部署 http: port: 80 # 管理员初始密码长度至少 8 位且必须包含大小写字母和数字 harbor_admin_password: Admin12345 # 数据库密码install.sh 会用它初始化 PostgreSQL database: password: Db2024harbor # 数据持久化目录务必放在磁盘空间充足的挂载点 data_volume: /data/harbor # 日志目录默认在 /var/log/harbor log: local: location: /var/log/harborhostname是最容易忽略的坑如果这里填了默认的reg.mydomain.com装完以后docker login和 push/pull 都会因为证书域名不匹配而失败必须改成实际访问的 IP 或内网域名。data_volume建议放到独立数据盘Harbor 的镜像存储、数据库文件都会写在这里根分区被撑满的教训我见过不止一次。3.3 Docker Compose 依赖检查离线机常缺这一环install.sh启动前会做环境检查其中一项就是 Compose。离线环境常见的两个状况一是完全没装 Compose二是只有 v1 的docker-compose没有 v2 插件。如果你只有 v1官方脚本也能用但要注意版本必须不低于 1.18.0。检查方法很简单docker-compose version如果提示command not found离线机又没有软件源最省事的办法是从另一台机器把docker-compose的 arm64 二进制直接拷过来放到/usr/local/bin/docker-compose并加执行权限。拷完验证一下能否打印版本号这一步不通过后面install.sh会卡在环境检查阶段。4. ARM 镜像准备与离线导入从拉取到 install.sh 的完整路径4.1 用 docker manifest 确认哪些镜像有 arm64 版本准备镜像之前先确认 Docker Hub 上这些镜像是否发布了 arm64 变体。docker manifest inspect命令可以直接查看某个 tag 支持哪些架构# 查看 core 镜像的多架构信息 docker manifest inspect goharbor/harbor-core:v2.4.0 # 只看架构列表用 python 提取更清晰 docker manifest inspect goharbor/harbor-core:v2.4.0 | python3 -c import sys,json; djson.load(sys.stdin); print([p[platform] for p in d.get(manifests,[])])输出里能看到{architecture: arm64, os: linux}之类的条目就说明官方发布了 arm64 变体。如果某个镜像的输出里只有 amd64那它在 ARM 上直接用不了需要考虑关闭对应组件——比如 trivy-adapter 在某些小版本上 arm64 镜像发布滞后我遇到这种情况就直接install.sh --without-trivy先跳过漏洞扫描不影响核心的 push/pull 功能。4.2 批量拉取 arm64 镜像并 save 成 tar 包最稳妥的镜像清单来源是解压出来的docker-compose.yml里的image字段。把这个文件拿到一台能联网的 arm64 机器上提取镜像名并逐个拉取# 从 docker-compose.yml 提取所有 image 字段去掉引号和重复项 grep -E ^\simage: docker-compose.yml | awk {print $2} | tr -d | sort -u images.txt wc -l images.txt # 逐个拉取自动获取 arm64 变体 while read img; do echo pulling $img ... docker pull $img || echo pull failed: $img done images.txt这里有个细节docker pull在 arm64 机器上会自动选择 linux/arm64 变体不需要手动指定平台。如果你是在 x86 机器上想拉 arm64 镜像需要加--platform linux/arm64参数但 save 出来的镜像在 load 时会有平台兼容的隐患我不建议这种跨平台做法老老实实在 arm64 机器上拉。拉取完成后把全部镜像打包成一个 tar 文件# 把 images.txt 里的所有镜像名传给 docker save docker save $(cat images.txt | tr \n ) -o harbor-arm64-images.tar ls -lh harbor-arm64-images.tardocker save支持一次打包多个镜像$(cat images.txt | tr \n )把每行一个的镜像名转成空格分隔的参数列表。打包出的 tar 就是后续离线安装的核心资产建议用md5sum记录一下校验值传输后核对防止大文件拷贝损坏。4.3 目标机上 load 镜像并替换离线包里的镜像 tar把harbor-arm64-images.tar拷贝到目标机后有两种使用方式。我用的是最不容易出错的方式直接替换离线包里的原镜像包。# 备份官方原始镜像包防止后续排查需要 mv harbor.v2.4.0.tar.gz harbor.v2.4.0.tar.gz.amd64.bak # 把 arm64 镜像包改名为原包名 mv /path/to/harbor-arm64-images.tar /opt/harbor/harbor.v2.4.0.tar.gz # 手动 load 一次确认镜像能正常导入 docker load -i /opt/harbor/harbor.v2.4.0.tar.gz | tail -5为什么替换而不是直接运行 install.sh因为install.sh内部会无条件 loadharbor.v2.4.0.tar.gz你提前 load 的镜像在脚本再次 load 时会被覆盖同 tag 的引用。替换成 arm64 包之后脚本加载的就是正确架构的镜像逻辑最干净。load 时注意观察输出如果有Loaded image: goharbor/harbor-core:v2.4.0这样的行就说明导入成功出现platform mismatch就要停下来检查镜像来源。4.4 执行 install.sh 启动 Harbor镜像准备好之后终于可以跑安装了cd /opt/harbor # 不启用漏洞扫描和 Chartmuseum先把核心服务跑起来 sudo ./install.sh --without-trivy --without-chartmuseum如果你确认准备的镜像列表里包含 trivy-adapter 和 chartmuseum 的 arm64 版本也可以不加这两个参数全量安装。脚本执行过程中会启动 prepare 容器生成配置然后逐个启动服务。结束后验证一下状态# 查看容器状态STATUS 应为 Up 或 healthy docker ps --format table {{.Names}}\t{{.Status}} # 查看启动日志确认没有报错 docker logs harbor-core --tail 20install.sh在这个阶段最常出的问题不是安装逻辑而是前置条件端口 80 被占用、data_volume目录权限不足、compose 版本过低。前两个问题在日志里会直接抛错第三个会在脚本开头环境检查时提示。把这三关过了Harbor 基本就能起来了。5. ARM 离线安装避坑5 个高频问题与排查5.1 registry 容器反复重启日志出现 exec format error现象docker ps看到 harbor-registry 和 harbor-core 等容器一直 restartingdocker logs里是exec format error或standard_init_linux.go:228: exec user process caused: exec format error。原因镜像架构不匹配。官方离线包的原生镜像全部是 amd64被 load 进了 arm64 机器内核执行二进制时直接拒绝。这是 ARM 离线安装最典型、也最容易误判为配置文件问题的现象。解决确认走完第 4 章的镜像替换流程用docker image inspect goharbor/harbor-core:v2.4.0查看镜像的Architecture字段是否为arm64。如果不是说明 load 的还是 amd64 包重新准备镜像。另外注意替换镜像包后要重新执行install.sh因为之前生成的 docker-compose 配置和容器卷可能已经被污染建议docker compose down -v清掉旧容器再装。5.2 容器起来了但 Web UI 打不开core 日志报数据库连接失败现象docker ps里容器都是 Up 状态但浏览器访问 IP 一直转圈docker logs harbor-core里出现failed to connect to database或dial tcp ...: Connection refused。原因数据库容器先启动但还没就绪时core 进程重试连接失败后退出了compose 又把 core 拉起来形成循环。更隐蔽的原因是harbor.yml里database.password和初始化时用的密码不一致。解决先看docker logs harbor-db确认 PostgreSQL 是否启动完成。如果是密码不一致编辑/opt/harbor/harbor.yml的database.password然后重新sudo ./install.shprepare 过程会重建数据库连接配置。数据卷目录权限问题也会导致 db 初始化失败检查data_volume目录所有者是否为当前用户必要时chmod -R 755或交给 root。5.3 docker login 成功push 镜像报 500 或 manifest 相关错误现象docker login正常docker push时返回500 Internal Server Error查看 registry 日志发现http: request body too large或存储驱动报错。原因多数情况是data_volume所在磁盘空间不足。Harbor 的 registry 层对磁盘写满的处理不优雅不会提前告警而是直接 500。另一个可能是 registryctl 的配置引用了不存在的存储路径。解决df -h检查数据盘Harbor 镜像仓库的数据增长远比想象快我习惯给data_volume所在分区预留至少 50GB。如果确认是存储路径问题检查/data/harbor/registry目录是否存在不存在就手动创建并确保 owner 是执行 install.sh 的用户。5.4 docker login 报 HTTPS 错误或 x509 证书问题现象客户端执行docker login http://192.168.10.20时提示http: server gave HTTP response to HTTPS client或x509: certificate signed by unknown authority。原因Harbor 默认配置是 HTTP 提供但 Docker 客户端默认走 HTTPS除非显式把该地址加入 insecure-registries 列表。这是内网部署最普遍的坑不是 Harbor 本身的问题。解决在所有需要 push/pull 的客户端机器上编辑/etc/docker/daemon.json{ insecure-registries: [192.168.10.20:80] }改完重启 dockersudo systemctl restart docker再重新 login。注意如果 Harbor 的端口不是默认 80insecure-registries里要写完整的IP:端口。5.5 install.sh 执行时报 compose 版本过低或缺失现象sudo ./install.sh刚开始就退出提示docker-compose version is too low或Cannot find docker compose。原因系统里没有安装 Compose或者只有 docker-compose v1 但版本低于 Harbor 要求的 1.18.0。离线环境经常出现这种情况因为安装 Compose 依赖软件源。解决从有外网的 arm64 机器上获取docker-compose-linux-aarch64二进制拷到/usr/local/bin/docker-composechmod x后验证版本。如果系统用的是 docker compose v2 插件检查/usr/local/lib/docker/cli-plugins/目录下是否有docker-compose文件没有就手动创建一个符号链接指向二进制文件。5.6 安装前 10 分钟体检清单与其装完再排查不如装前花 10 分钟跑一遍体检。我每次部署都会按这个顺序过一遍# 1. 架构确认 uname -m # 2. 磁盘空间/data 至少 50G 可用 df -h /data # 3. 端口占用80/443/8080 不能被占用 ss -lntp | grep -E :(80|443|8080)\b # 4. compose 版本 docker compose version || docker-compose version # 5. 当前时间偏差偏差大于 5 分钟会导致 token 校验失败 date timedatectl status # 6. 镜像架构抽查 docker image inspect goharbor/harbor-core:v2.4.0 | grep Architecture时间同步这个坑最玄学Harbor 的 JWT token 签发和数据库会话都依赖时间一致性某次部署时容器全部正常但登录后 API 调用全部 401查了半天发现是内网机器时间慢了 3 分钟。离线环境没有 NTP 出口时至少手动date -s校准一次最好配置内网时间源。6. 验证与进阶把 Harbor 交给 systemd重启后不丢服务安装完成后的验证我习惯跑一套完整的“登录 - 打标 - push - pull”闭环而不是只看容器状态。先创建测试项目再走一遍客户端全流程# 登录 Harbor docker login 192.168.10.20 -u admin -p Admin12345 # 拉一个测试镜像打个 tag项目名 library 是默认公共项目 docker pull busybox:latest docker tag busybox:latest 192.168.10.20/library/busybox:test # push 上传 docker push 192.168.10.20/library/busybox:test # 删除本地镜像后 pull 回来验证存储和代理链路 docker rmi 192.168.10.20/library/busybox:test docker pull 192.168.10.20/library/busybox:test这套流程走通说明 registry 存储、数据库、认证、nginx 转发整条链路都是健康的。只验证docker ps是远远不够的——容器活着不代表服务可用。一个必须处理的进阶问题是开机自启。install.sh完成的容器编排在重启机器后不会自动拉起内网服务器重启是常态我习惯写一个 systemd unit 托管整个 compose[Unit] DescriptionHarbor Docker Compose Service Requiresdocker.service Afterdocker.service docker.socket [Service] Typeoneshot RemainAfterExityes WorkingDirectory/opt/harbor # v2 插件用下面的命令 ExecStart/usr/bin/docker compose up -d ExecStop/usr/bin/docker compose down # 如果你的环境只有 v1改成 # ExecStart/usr/local/bin/docker-compose up -d # ExecStop/usr/local/bin/docker-compose down StandardOutputjournal [Install] WantedBymulti-user.target把这段存到/etc/systemd/system/harbor.service然后systemctl daemon-reload并systemctl enable harbor。注意RemainAfterExityes是必须的因为compose up -d是后台拉起容器后立即返回没有这个标记 systemd 会认为服务已退出。这套流程我前前后后部署过好几轮最大的体会有两点一是 ARM 离线安装的每一步都要验证“架构”而不是验证“文件存在”镜像 load 成功不代表能运行二是离线环境的排错手段有限把体检清单前置比装完再面对黑匣子高效得多。镜像准备脚本和 systemd 文件建议留存到自己的工具集里换机器换版本时改改镜像列表就能复用。希望帮到你。本文还有配套的精品资源点击获取