☰
ARM离线部署Harbor v2.4.0全流程避坑指南
2026/10/20 2:51:16 网站建设 项目流程

简介:面向ARM架构服务器的Harbor v2.4.0离线安装包,专为内网或无外网环境下快速搭建镜像仓库而准备,适合运维与平台部署人员使用。压缩包共6个文件,包含两个shell脚本(安装脚本与公共函数库)、一个gz格式的Docker镜像文件、一份harbor.yml配置模板、LICENSE许可文件以及prepare准备脚本,整体约402.34MB,结构精简,便于归档与分发。使用前需自行安装Docker与Docker Compose,随后执行install.sh即可一键部署,省去手动拉取镜像与配置环节。目前已有1576人学习下载,适用于国产化设备或ARM服务器上的Harbor落地场景。配置模板与准备脚本还能辅助用户按实际环境调整参数,实现离线、规范化的部署流程。

1. 离线部署的旋涡:ARM 上装 Harbor v2.4.0 为什么老失败

第一次在 ARM 服务器上离线部署 Harbor v2.4.0,我并没有把它当成多难的活——离线包有、Docker 有、配置文件照着模板抄一遍就行。但真实情况是:同一个安装包在 x86 机器上一次跑通,换到 ARM 平台后容器全部起来又退回去,日志里没有“架构不匹配”这种高亮报错,只有 core 反复重启、数据库连不上这类让人怀疑人生的信息。折腾两天后发现,问题出在离线包里内置镜像的 CPU 架构和服务器不一致,这种问题只在 ARM 环境暴露得特别明显。

Harbor 作为私有镜像仓库主流方案,离线安装本来就有门槛:安装包体积大、组件多、配置项敏感,叠加 ARM 架构后,网上很多 x86 教程直接失效。这篇文章适合正在给无外网的 ARM 开发环境搭建 Harbor、想在两小时内跑通的开发者。我会从版本核对开始,把离线包、harbor.yml、prepare、install、验证的完整链路写到最后一步,中间那节「常见问题与排查」按现象、原因、解决三段式记录我真实翻过的车。

2. 环境核对与版本选择:ARM 上装 Harbor v2.4.0 的硬前提

2.1 先看清目标架构,aarch64 和 armv7 是两个世界

一切从确定你面对的是哪种 ARM 开始。Harbor v2.4.0 的离线包按架构区分,x86_64 和 arm64 是两组完全不同的内置镜像。Docker 本身可以跑带 multi-arch manifest 的通用镜像,但 Harbor 离线包里的镜像归档是固定架构的,load 到本地后不会自动转换。检查这一步花不了三十秒,但能帮你避开一整天的无效排查。

uname -m docker info --format '{{.Architecture}}'

第一行看 Linux 内核视角下的 CPU 架构,第二行看 Docker daemon 实际运行的架构。我见过不少设备 uname 输出 aarch64、docker info 也正常显示 arm64,这种直接下载 arm64 离线包就行。麻烦的是 uname 返回 armv7l、或者 ARMv8 跑在 32 位模式下的机器,这类 32 位 ARM 环境基本可以放弃 Harbor v2.4.0,因为组件镜像没有 armv7 层。简单说:Harbor v2.4.0 的 ARM 目标平台是 aarch64/arm64,不是所有带“ARM”字样的设备都能装。

2.2 锁定 v2.4.0 的原因:版本漂移在离线环境是灾难

离线安装最怕版本漂移。latest 包今天拉下来的构建号和明天不一定一致,而且 Harbor 在较新版本里对 ARM 平台组件的调整很频繁,内网一旦断网,想升级只能重新拷包。选 v2.4.0 这个相对稳定的版本,是因为它的离线安装流程和 docker-compose 的配合足够成熟,配置模板干净,组件之间没有太多需要手工桥接的部分。另一个实际考虑是 x86 教程多,ARM 排错资料虽然少,但已知问题能按版本号去核对,不像新版本发布初期的黑匣子阶段。

离线包的来源也值得说一句。官方 release 页面会同时提供 x86_64 和 arm64 两种离线安装包,资源名通常长得很像,就可能只差一个 arm64 后缀,内网镜像站混放目录的情况也不少。拿包时下意识对比一下文件名里的架构标识,再结合后面的 docker image inspect 做二次确认,能挡掉不少坑。如果内网镜像站缺 ARM 包,也可以在有公网的过渡机上下载,确认无误再拷回来。

2.3 Docker 与 docker-compose 的版本基线

Harbor 的 install.sh 在内部调用 docker-compose 来编排容器,所以这台机器上的 compose 版本直接决定脚本能不能跑通。建议先把 Docker 升到 20.10 以上,docker-compose 至少是 v2 的稳定版。

docker --version docker compose version docker-compose --version

三条命令分别看 Docker 本体和 compose 的两种形态。ARM 发行版通常自带 Docker 20.x,但有些精简系统装的是很老的 docker-compose v1,install.sh 可能直接报“command not found”。我的经验做法是把 compose v2 的二进制放到 /usr/local/bin/docker-compose,再确认 PATH 里能命中这个名字,否则安装脚本里旧式的 docker-compose 调用会失败。另一个容易忽略的是 storage driver,建议保持 overlay2。可以顺手查一下:

docker info | grep "Storage Driver"

如果输出是 vfs,Harbor 跑起来会慢得让人误以为是资源不足。vfs 每次写入都做完整拷贝,镜像层越多越明显,有条件的话迁移回 overlay2 再继续。

2.4 磁盘、内存和数据卷的预算

离线包解压后,安装目录加镜像归档通常要占好几个 GB;docker load 之后镜像还会在 /var/lib/docker 再占一份空间。数据卷是长期增长点,registry 每收到一个镜像就存一份,数据库和 redis 的持久化也在里面。起步建议给系统盘留足 20GB,数据目录按“未来三个月预计镜像体积 ×2”去估,不要低于 50GB。

目录用途建议最小空间
/opt/harbor安装程序与镜像归档5GB 以上
/var/lib/dockerDocker 镜像与容器层20GB 以上
/data/harborHarbor 数据卷50GB 起步

检查时用df -h / /opt /var/lib/docker和free -h。很多 ARM 开发板的根分区只有十几 GB,外部扩展盘挂 /data,这种布局反而好用:安装目录放系统盘,data_volume 放扩展盘。但注意扩展盘格式化成 ext4,别用 vfat——Harbor 的数据库目录在 vfat 上写权限会出各种奇怪报错。内存方面,完整 Harbor 组件建议 4GB 起步,两三百 MB 的入门板子硬装全套很难受,后面 install.sh 阶段就要主动砍掉可选组件。

3. 离线包解压与镜像装载:把 ARM64 镜像喂给 Docker daemon

3.1 解压后先列清单,别急着跑脚本

拿到正确的 arm64 离线包后,把它传到目标机的 /opt 下,第一步解压:

tar -zxf harbor-offline-installer-v2.4.0-arm64.tgz -C /opt/ cd /opt/harbor ls -lh

解压完成后的目录里至少会有 install.sh、prepare、common.sh、harbor.yml.tmpl 和镜像归档,镜像归档通常以 harbor.v2.4.0.tar.gz 这类命名。我每次都会先 ls -lh 看三个信息:install.sh 和 prepare 有没有可执行权限、镜像归档大小和磁盘剩余空间是否匹配、harbor.yml.tmpl 是否存在。如果压缩包是从 Windows 共享目录拖过来的,解压后很可能丢 x 权限,等会儿 prepare 一跑就报 permission denied,不如现在一眼看出来。

顺手做一次校验更稳妥:

sha256sum harbor.v2.4.0.tar.gz

把算出来的哈希值跟 release 页面或内网镜像站提供的对比,能提前发现下载不完整或资源被替换的情况。离线安装一切依赖本地文件,如果镜像归档有问题,后面 load 到一半才报错,定位成本比现在高得多。

3.2 docker load:把镜像归档倒进本地镜像库

docker load -i harbor.v2.4.0.tar.gz

参数 -i 指定输入文件,执行过程会按镜像层逐个还原,输出一长串“Loaded image”行。这一步耗时取决于磁盘速度,机械硬盘上通常十几分钟到半小时,SSD 会快很多。如果中途进度条消失,先去df -h /var/lib/docker看空间是不是已经满了——离线归档在 load 时会展开成好几个 GB 的镜像层,16GB 系统盘很容易见底。

load 完最重要的一件事:列一下镜像清单,确认组件版本齐全。

docker images | grep goharbor

正常能看到 goharbor/harbor-core、goharbor/harbor-portal、goharbor/harbor-db、goharbor/harbor-jobservice、goharbor/registry-photon、goharbor/nginx-photon、goharbor/redis-photon 这一整组。数量少任何一个,都说明离线包不完整,重新下载比强行继续安装有用。

3.3 用 docker image inspect 判断离线包架构

如果离线包目录名和来源都没有明确标识,拿不准手里这份是不是 ARM 版,最直接的验证命令是这一条:

docker image inspect goharbor/harbor-core:v2.4.0 --format '{{.Architecture}} {{.Os}}'

正常输出应该是 arm64 linux。如果这里显示 amd64,后面无论 prepare、install 怎么调都是白费——容器在 ARM 机器上能拉起一部分,但跑一会儿就以各种姿势退出。我遇到过内网镜像站把 x86 离线包直接复制到 ARM 目录下的情况,文件名一字未改,只有检查镜像架构能看出来。这一步做完再进配置阶段,整个安装的把握会大很多。

3.4 大文件传输后的后悔药:md5 和 scp 的时间成本

离线包动辄几个 GB,从有网机器搬到内网 ARM 设备时,U 盘或 scp 都行,但传输后一定要重新校验。scp 传完可以再跑一次md5sum对比源文件哈希;U 盘拷贝则要注意 FAT32 单文件 4GB 上限,超过就要分割或用 exFAT/NTFS。这个环节翻过车的人都知道,tar 解压到一半报 “Unexpected EOF” 才是最浪费时间的——压缩包不完整,前面传输时间全白费。

另外,如果是从镜像仓库直接准备 ARM 镜像,也可以用过渡机 docker pull 后再 docker save 成单文件,但这需要把依赖的所有 goharbor 组件都拉完整。离线安装场景里,这种手工做法效率低、容易漏组件,不如直接找对应架构的离线安装包。毕竟离线包在发布前已经把组件镜像和配置模板打包好了。

4. 配置 harbor.yml:最容易出错的五个参数

4.1 复制模板并注意 YAML 缩进

配置文件的起点是把模板复制成正式文件:

cd /opt/harbor cp harbor.yml.tmpl harbor.yml vim harbor.yml

harbor.yml 是 YAML 格式,缩进必须用两个空格,不能混入 tab。很多 ARM 设备上从 Windows 编辑过的模板带上了不可见字符,prepare 阶段解析就直接报错。我自己习惯复制后用cat -A harbor.yml | tail -30快速扫一眼有没有^M这种回车符残留,有的话先sed -i 's/\r$//' harbor.yml清掉。别小看这一步,至少省掉一次“配置无效”的报错。

4.2 hostname 和端口:最容易写错的地方

harbor.yml 里最重要的三段是 hostname、http、https。看一个内网 HTTP 场景的配置示例:

hostname: 192.168.10.23 http: port: 80 # https: # port: 443 # certificate: /data/harbor/server.crt # private_key: /data/harbor/server.key data_volume: /data/harbor

hostname 直接写内网 IP 或内部域名,不要带 http:// 前缀,也不要带端口号。写成https://harbor.local这种形式,prepare 在解析阶段就会因 scheme 报错。http.port 默认 80,如果设备上已有 nginx、apache 或别的服务占用了 80,就改成 8080 或别的空闲端口,注意后续 docker login 和 push 都要带上这个端口。

4.3 HTTPS 的选择:离线环境优先关掉

如果内网没有正式证书,我建议把整个 https 段注释掉,只留 http。这样 prepare 不会去校验证书路径,nginx-proxy 与 core 内部的 TLS 配置也会走默认的简化逻辑,少一层报错。以自签名证书启用 HTTPS 虽然也能跑,但浏览器每次访问都要点信任,开发环境里反而制造障碍。

如果确实需要 HTTPS,先准备证书再填路径:

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ -keyout /data/harbor/server.key \ -out /data/harbor/server.crt

然后让 harbor.yml 里的 certificate 和 private_key 指向这两个绝对路径。证书文件属主设为 root 即可,Harbor 的 nginx 容器以 root 启动,读取没有问题。

4.4 data_volume 权限与容器 UID 10000

配置里最容易忽略的是 data_volume 目录的属主。Harbor 容器内的进程大量以 UID 10000 运行,外部挂载的目录属主必须匹配,否则核心服务会悄悄出现 Permission denied。

mkdir -p /data/harbor chown -R 10000:10000 /data/harbor

这两条命令在修改 harbor.yml 之前就要做。我看到很多人配好了路径、跑完了 install.sh,最后在页面 502 和日志权限错误之间反复横跳,最后才发现数据目录忘了 chown。这个操作对 ARM 环境尤其重要,因为 ARM 设备常见的外部盘 mount 参数可能带了 noacl,权限判断比 x86 服务器更严格。

4.5 管理密码与可选组件

harbor.yml 里如果保留了 harbor_admin_password 字段,默认值就是 Harbor12345,有的构建版本没保留这个键不影响首次安装,Web 界面初始登录同样是 admin/Harbor12345。离线环境我建议首次登录后立刻改掉,改完再对外提供地址。

另外确认一下配置里没有开 trivy 自动下载相关选项。ARM 离线环境没有外网,漏洞数据库根本拉不动,保持默认不带--with-trivy是最稳的,这能让内网小内存设备跑得更干净。配置改完不要直接 install.sh,先跑一次 prepare,让新的 harbor.yml 参与配置生成,再进入安装流程。

5. 安装过程的常见问题与排查:prepare 到 install.sh 的避坑指南

5.1 prepare:先把配置装配成可运行的 compose 文件

cd /opt/harbor ./prepare

prepare 的作用是检查 Docker daemon 状态、解析 harbor.yml、生成证书和内部配置文件。成功执行后会生成 docker-compose.yml 以及 common/config 下的各类组件配置,这一步不通过不要强行 install.sh。常见报错集中在两类:第一类是 yaml 解析失败,基本是缩进问题或 hostname 写错;第二类是 Docker 连接失败,确认 daemon 是否在跑、当前用户是否在 docker 组里。

systemctl status docker groups

如果当前用户不在 docker 组,prepare 可能提示权限不足。执行sudo usermod -aG docker $USER后重新登录再跑,不要全程 sudo 去执行安装脚本,shell 环境变量容易出偏差。

5.2 install.sh:镜像自动装载与容器编排

prepare 通过后再执行:

./install.sh

install.sh 会先检查本地镜像是否存在,没有就从镜像归档里 load,然后调用 docker-compose 启动一整组容器。执行成功的标志是最后出现类似 “Harbor has been installed and started successfully” 的提示。如果选择了--with-trivy,它还会额外启动漏洞扫描组件,这个参数在 ARM 离线环境下不建议开启,服务器断网时组件会空转重试。等待启动完成后执行docker-compose -f /opt/harbor/docker-compose.yml ps,看到的容器都处于 Up 状态,才说明编排阶段过了。

5.3 避坑实例:镜像架构不符,容器反复退出

现象:docker ps 看到 harbor-core、harbor-jobservice 甚至 registry 都在 restarting,docker logs 里偶尔出现类似 exec format error 的提示,更多时候只是很普通的连接失败。

原因:离线包内置镜像实际是 amd64,load 到 ARM 设备后执行二进制时对不上指令集。部分 Go 编写的容器能启动,但一进入业务逻辑就崩溃,日志反而像数据库问题。

解决:别在日志里耗时间,直接跑docker image inspect goharbor/harbor-core:v2.4.0 --format '{{.Architecture}}',确认是否 arm64。不是就重新下载正确架构的离线包,之前 load 进来的错误镜像可以用docker rmi清理掉再装。

5.4 避坑实例:core 容器反复重启,数据库连接失败

现象:harbor-db 已经 Up,但 harbor-core 启动后十几秒就退出,日志里报数据库连接失败或初始化失败。

原因:常见有两个。第一是 data_volume 目录属主不对,容器里的 postgres 或 core 组件写不了初始化文件;第二是第一次启动时 harbor-db 还在初始化,core 等不及就崩了,但正常情况下 compose 的重试策略不会一直失败,持续重启基本还是权限问题。

解决:先停掉整套docker-compose down,确认 /data/harbor 属主是 10000:10000,中间嵌套的 database、registry 等子目录也要一起检查和修复。然后用docker-compose -f /opt/harbor/docker-compose.yml logs --tail=200 harbor-core看具体错误,修复后重新 up。记住改过一次数据卷权限,重装时旧数据还在,不要轻易删 database 子目录。

5.5 避坑实例:80 端口被占导致页面打不开

现象:install.sh 显示安装成功,浏览器访问 IP 却一直连接重置,连curl 127.0.0.1:80都失败。

原因:设备上已有 nginx、haproxy 或某容器监听了 80 端口。Harbor 的 nginx 组件绑定 80 失败时,install.sh 有时候不会及时暴露,等到访问页面才发现一切静悄悄。

解决:把 harbor.yml 里 http.port 改成 8080,重新./prepare && ./install.sh。端口改成 8080 后,后面 docker login、docker push 的地址都要带端口,推镜像命令就变成docker login 192.168.10.23:8080这种形式。

5.6 避坑实例:磁盘写满,load 到一半直接失败

现象:docker load 执行到一半报 no space left on device,或者 install.sh 在编排阶段失败,提示容器创建内存不足。

原因:/var/lib/docker 所在分区空间不够,或者 inode 耗尽。ARM 设备的小分区经常在离线包镜像展开时被塞满。

解决:docker system df 查看镜像和容器占用,必要时清理旧镜像腾空间。如果设备只有不足 16GB 系统盘,最好的办法是把 Docker 数据目录迁到大分区,修改 daemon.json 的>docker-compose -f /opt/harbor/docker-compose.yml logs --tail=200 harbor-core

--tail=200 指只看最近 200 行,-f 参数可以持续跟踪。需要单独确认数据库状态时,把最后一个参数换成 harbor-db,日志里能看到 postgres 启动的进度。这套命令是排查容器内问题的主要手段,page 502、登录失败、推送超时,最终都能在某个组件的日志里找到触发线索。

6. 装完怎么验证:健康检查、登录仓库、推拉一个镜像

6.1 用 API 先做健康检查

安装结束后,第一件事是用 API 验证整体状态。我这里假设用的是 HTTP 端口 8080:

curl http://192.168.10.23:8080/api/v2.0/healthz curl -u admin:Harbor12345 http://192.168.10.23:8080/api/v2.0/systeminfo

第一条返回字符串 OK,说明 nginx 到 core 之间的链路是通的。第二条带登录凭证访问 systeminfo,如果返回一段 JSON,其中有 harbor_version 为 v2.4.0 这样信息,就说明数据库、核心服务和认证链路都正常。先跑这两条再开浏览器,至少别让 HTTP 层面问题误导到容器排查。

6.2 docker login 和真实推拉测试

API 通了,还要用真实操作把镜像“走”一遍。在一台能访问这台 Harbor 的开发机上执行:

docker login 192.168.10.23:8080 -u admin docker pull alpine:3.16 docker tag alpine:3.16 192.168.10.23:8080/library/alpine:3.16 docker push 192.168.10.23:8080/library/alpine:3.16

docker login 进入交互式密码输入,密码填当前有效的 Harbor 管理员密码。push 成功后,再从另一台机器把这个镜像 pull 下来,或在本机删掉本地 tag 后重新拉取,能确认存储和调度链路都正常。如果 push 时报了 “denied: requested access to the resource is denied”,基本是项目权限问题,library 项目应该让 admin 有推送权限,嫌疑通常落在登录凭证过期或命令行端口写错。

6.3 从教训里固化一个验证习惯

整套验证流程做完不到五分钟,却可以挡住九成的交付事故。从那以后我每次在 ARM 设备上装完 Harbor,都会强制按这个顺序走一遍:先 curl healthz 看服务存活,再 docker login 试凭证,最后 push 和 pull 一个小镜像确认读写链路,全部通过才把地址交出去。这个习惯帮我避开了至少两次“装好了但没真正跑通”的尴尬情况。

希望这篇记录能帮你少踩几个我已经踩过的坑,尤其是离线包架构一定要提前确认,Harbor 的 ARM 部署就不再是玄学。

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

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

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

立即咨询