简介:针对ARM64架构的Harbor 2.8.2离线安装包,专为边缘计算、物联网及企业内网等容器镜像部署场景打造,解决无网络或弱网环境下安装企业级镜像仓库的痛点。压缩包共6个文件,包含install.sh与prepare安装脚本、harbor.v2.8.2-arm64.tar.gz主程序包、harbor.yml.tmpl配置模板、LICENSE许可文件及common.sh公共脚本,总大小约639.65MB,结构清晰,解压后即可按官方手册完成部署。已有260人学习下载,读者可获得完整离线安装组件,配合配置模板可灵活定制存储后端、权限控制、镜像复制与扫描等企业级功能,尤其适合ARM低功耗设备或保密网络环境。这份离线包免去了联网拉取镜像的环节,在离线交付或涉密部署中尤为实用,可显著提升部署效率与镜像管理安全性。对于ARM服务器集群、边缘节点等受限环境,该安装包是高效落地的实用选择。
1. 在 ARM64 机器上离线交付 Harbor:这个 v2.8.2 离线包就是正解
一台鲲鹏 920、飞腾或者 RK3588、树莓派 4B,放在隔离网络里,要交付一套企业级镜像仓库。这种场景下最省事的路径不是配镜像源慢慢拉组件镜像,而是直接拿harbor-offline-installer-v2.8.2-arm64.tar.gz这个离线包:解压、改两处配置、执行install.sh,registry、core、portal、notary 这些组件一次就位。它解决的是 ARM64 + 无公网环境下 Harbor 装不上、装得慢、装完不知道哪里出错的问题。适合做内网交付的运维、信创环境部署的工程师,以及想把镜像仓库快速跑起来的团队。下文从选型逻辑说到安装步骤,再把我踩过的坑和验证手段完整过一遍。
2. 选型背后:ARM64、v2.8.2 与离线包的三个决定
2.1 ARM64 不是换了个 CPU 那么简单
Harbor 全家桶由十几个组件镜像组成,每个镜像都按平台单独构建。官方发布页上区分amd64和arm64的离线包,原因就在于镜像 manifest 里的linux/arm64与linux/amd64不能混用。你在一台 ARM64 机器上执行docker pull,默认会去拉当前节点架构的镜像,这个逻辑没问题;但若是拿着 x64 的镜像硬塞进 ARM 节点,就会遇到两种局面:要么 manifest 不匹配直接报no matching manifest for linux/arm64,要么用 qemu-user 模拟跑起来。
qemu 模拟能起容器,看起来好像能用,实际上是个黑匣子。系统调用翻译带来的开销在 registry 这种大量读写磁盘的组件上尤其明显,镜像推送稍大一点就卡得没法看。更麻烦的是遇到 io_uring、openat2 这类新系统调用,qemu 翻译层不一定跟得上,容器起来以后莫名崩溃,排查成本极高。所以结论很直接:ARM64 节点就用 ARM64 的离线包,不要用 qemu 模拟 x64 容器当生产方案。
这个离线包的价值就是把「手动处理平台匹配」这件事彻底干掉。包内的镜像压缩档已经全部标记为linux/arm64,install.sh执行时依次docker load进去,不再需要你在 Docker Hub 上一个个找 arm64 tag。对隔离网络来说,这才是真正能落地的路径。
2.2 为什么是 v2.8.2 而不是更新的版本
Harbor v2.8.2 在 2.x 系列里属于功能完整、生态兼容性很好的一个版本。它的安装流程还走经典docker-compose流程,不强制要求 Docker Engine 自带的 compose v2 插件,对 CentOS 7、Ubuntu 18.04 这类自带老版本 Docker 的 ARM 服务器非常友好。再往后的版本逐步提高了对 Docker 和 compose 的版本要求,在老设备上反而容易出现前置检查过不去的情况。
从功能角度看,v2.8.2 已经把企业镜像仓库该有的能力都收进来了:v2.0 API、RBAC 权限模型、镜像复制、漏洞扫描、垃圾回收、配额管理、审计日志,内网交付完全够用。另外,如果团队后续有升级计划,从 2.8.x 走到 2.9、2.10 的迁移路径官方是覆盖的,先跑新版本的 migrator 做数据库迁移即可,不用推倒重来。综合老硬件兼容性和后续升级空间,v2.8.2 是一个卡在「稳」和「新」之间的位置。
2.3 离线包和在线包、源码包的区别
Harbor 官方给三种形态:online installer、offline installer、源码包。Online installer 只有脚本和 yml 模板,执行时联网拉镜像,隔离网络里直接抓瞎;源码包需要自己有一套构建环境去 make,适合二次开发,不适合交付场景。这个标题里的 offline 版本是唯一适合生产交付的形态。
离线包解压后,目录里有harbor.v2.8.2.tar.gz这样的镜像压缩档,所有组件镜像都封在里面。install.sh的第一步就是把这几十个镜像 load 进 Docker,然后才生成并启动容器。这里有一个硬性要求要提前说清楚:离线包本身有两三个 GB,load 进 Docker 后/var/lib/docker至少要留出 10GB 以上空间;data_volume默认指向/data,镜像仓库的存储、PostgreSQL 数据、Redis 数据全落在这里,磁盘规划时得单独给它划一块大分区,不能指望根分区那几十 GB 硬扛。
3. 动手部署:解压、配置、install.sh 三步走
3.1 环境检查:先把依赖和端口确认掉
ARM64 设备上的 Docker 环境千奇百怪,我见过树莓派上装的 Docker 版本旧到连docker compose子命令都不存在。部署前先做一轮系统检查,把依赖、端口、磁盘一次看清楚。
docker version --format '{{.Server.Version}}' docker-compose version ss -lntp | grep -E ':80|:443' df -h /data /var/lib/docker第一条命令拿到 Docker daemon 版本号,Harbor v2.8.2 对 Docker 的最低要求比较宽松,但建议至少 20.10 以上。第二条检查docker-compose是否可用,安装脚本会检测 compose 版本,低于 1.29 会直接报错退出。第三条看 80 和 443 端口占用情况,Harbor 默认的 nginx 入口就是这两个端口,ARM 小机器上经常有别的服务占着。第四条确认/data和/var/lib/docker的剩余空间,镜像仓库跑起来后磁盘增长比想象中快得多。
如果检查发现docker-compose命令不存在,常见做法是手动放置 compose 插件二进制:
mkdir -p /usr/local/lib/docker/cli-plugins cp docker-compose-linux-aarch64 /usr/local/lib/docker/cli-plugins/docker-compose chmod +x /usr/local/lib/docker/cli-plugins/docker-compose docker compose versiondocker-compose-linux-aarch64这个文件提前在联网的机器上下好,拷贝进隔离网络即可。放在cli-plugins目录后,docker compose子命令就能用了,老式的docker-compose命令也兼容,Harbor 安装脚本两种方式都能识别。
3.2 解压与 harbor.yml 配置:两个地方的参数决定成败
离线包解压后进入harbor目录,第一步先复制配置模板,再逐项修改。
tar -xzf harbor-offline-installer-v2.8.2-arm64.tar.gz cd harbor cp harbor.yml.tmpl harbor.yml sed -i 's/^hostname: .*/hostname: 192.168.10.20/' /data/harbor/harbor.yml sed -i 's/^ port: 80/ port: 8080/' /data/harbor/harbor.ymlhostname这个参数是坑最多的一个,它不只影响 Web 页面访问,还决定 nginx 反向代理的转发目标以及客户端docker login时使用的地址。这里必须填客户端实际能访问到的 IP 或域名,不能填127.0.0.1。端口方面,如果 80 被占用,直接把http.port改成 8080 最省事,后续浏览器访问和docker login都带着:8080即可。
接下来设置管理员密码和数据库密码:
sed -i 's/^harbor_admin_password: .*/harbor_admin_password: YourStrongPass123/' /data/harbor/harbor.yml sed -i 's/^ password: .*/ password: YourDBPass456/' /data/harbor/harbor.ymldatabase段里的password是 PostgreSQL 的 root 密码,prepare阶段会写进生成的 docker-compose 配置。这个密码后面再改非常麻烦,安装前就定好。harbor_admin_password是 Web 控制台管理员密码,默认值是Harbor12345,内网环境也必须改掉,不然等于裸奔。
我把关键参数整理成一张表,部署时对照着看:
| 参数 | 默认值 | 建议 | 说明 |
|---|---|---|---|
hostname | reg.mydomain.com | 节点实际 IP 或内部域名 | 客户端访问和 docker login 都依赖它 |
http.port | 80 | 未被占用的端口 | 如 8080,避免与现有服务冲突 |
harbor_admin_password | Harbor12345 | 强密码 | Web 管理员初始密码 |
database.password | 随机串 | 固定强密码 | PostgreSQL root 密码,安装后再改麻烦 |
data_volume | /data | 大分区路径 | 镜像、数据库、Redis 都在这 |
3.3 prepare 与 install.sh:这条链路做了什么
配置改完后执行安装:
./prepare ./install.sh --with-notary --with-trivyprepare做的事情是基于 harbor.yml 渲染出 nginx 配置、生成证书和密钥,并最终生成docker-compose.yml。这里有两点要注意:一是docker-compose.yml是生成出来的,不要手动改,改了也会在下次 prepare 时被覆盖;二是如果配置了 HTTPS,证书路径要提前准备好,写在https.certificate和https.private_key两个字段里。
install.sh会先加载离线包内的镜像压缩档,然后启动所有容器。--with-notary开启镜像签名组件,--with-trivy开启漏洞扫描。需要说明的是,--with-trivy在离线环境有个隐患:trivy 漏洞库需要联网初始化,隔离网络里首次扫描会失败。如果业务上不强依赖漏洞扫描,建议这个参数先不加,省掉一个不定时炸弹。
安装完成后验证容器状态:
docker ps curl http://192.168.10.20:8080/api/v2.0/pingdocker ps确认所有容器都是 Up 状态,重点看harbor-core、harbor-registry、harbor-portal、harbor-db、harbor-nginx。第二条命令请求 Harbor 的 API 健康检查接口,返回字符串Pong表示核心服务正常。
4. 避坑与排查:ARM 上部署 Harbor 的四个高频故障
4.1 install.sh 卡在 docker-compose 版本检查
现象:执行install.sh时输出[ERROR] docker-compose version (1.18.0) is too low, please upgrade docker-compose to at least 1.29.0,安装流程直接中断。
原因:ARM 设备上很多系统自带的 docker-compose 是远古版本,比如 Ubuntu 18.04 的 apt 源里那个 1.18.0。Harbor 的common.sh脚本会检测 compose 版本,低于 1.29 直接拒绝继续执行,避免后续编排出问题。
解决:按 3.1 里写的方式,把 compose v2 的二进制放到cli-plugins目录并赋予执行权限。放好后重新跑install.sh即可。这里注意不要用apt install docker-compose去升级,装完大概率还是老版本。
4.2 容器全在运行,但浏览器访问显示 502
现象:docker ps看所有容器都是 Up,但浏览器打开 Harbor 页面显示 502,或者docker login报连接被拒。
原因:hostname配置和实际访问地址不一致。Harbor 的 nginx 配置由prepare生成,转发目标就是 harbor.yml 里那个 hostname。如果你把 hostname 写成127.0.0.1,本机能访问,局域网其他机器过来就全部 502。
解决:把harbor.yml里的 hostname 改成实际访问 IP,重新执行./prepare && ./install.sh。install.sh会基于新配置重新生成 nginx 配置和容器编排,不需要清掉数据卷。
4.3 磁盘被 /data 撑爆,GC 跑不动
现象:部署一段时间后磁盘告警,registry 容器反复重启,Web 页面操作报 500,触发垃圾回收时任务一直停在 Pending 状态。
原因:data_volume默认指向根分区的/data。ARM 设备尤其是树莓派、RK3588 开发板,根分区往往只有 16GB 或 32GB,镜像仓库的存储、PostgreSQL 数据文件、Redis 持久化数据全写在这里,几天就满了。
解决:部署前用df -h看清楚哪块盘空间大,把data_volume改到独立分区。部署完成后才发现空间不够,迁移数据卷是件痛苦的事,带着 PostgreSQL 和 registry 目录做 rsync,期间服务还不能停。
4.4 docker login 报 x509 证书错误
现象:客户端执行docker login 192.168.10.20:8080,报错x509: certificate signed by unknown authority。
原因:Harbor 默认使用自签名证书,客户端 Docker daemon 不在信任列表里,登录时证书校验失败。
解决:内网环境最直接的方式是把 Harbor 地址加到客户端的 insecure-registries,修改/etc/docker/daemon.json:
{ "insecure-registries": ["192.168.10.20:8080"] }然后重启 Docker 服务再登录。如果公司安全规范要求 HTTPS,那就把 Harbor 生成的ca.crt拷贝到每台客户端的/etc/docker/certs.d/192.168.10.20:8080/目录下,效果一样但更规范。
5. 验证与日常维护:交付前把这些检查做一遍
5.1 完整链路验证:登录、推送、拉取
Harbor 装完不是docker ps全 Up 就能交差的。我会强制走一遍完整的镜像推送拉取链路,这条链路能暴露证书、权限、存储、网络四个方面的问题。
docker login 192.168.10.20:8080 -u admin docker tag nginx:alpine 192.168.10.20:8080/ops/nginx:alpine docker push 192.168.10.20:8080/ops/nginx:alpine docker pull 192.168.10.20:8080/ops/nginx:alpinedocker login验证认证体系,注意这里会触发 x509 证书检查,如果配置了 insecure-registries 则跳过。docker tag给镜像打上 Harbor 仓库地址,仓库地址格式是Harbor地址/项目名/镜像名:tag。docker push之前先确保ops这个项目已经在 Web 控制台建好,推送到不存在的项目会报NAME UNKNOWN。docker pull验证镜像能完整拉回来,确认存储和 registry 组件的数据通路正常。
如果用命令行建项目,可以走 API:
curl -u admin:'YourStrongPass123' -X POST \ 'http://192.168.10.20:8080/api/v2.0/projects' \ -H 'Content-Type: application/json' \ -d '{"project_name":"ops","public":true}'public: true表示项目公开,局域网内所有登录用户都能直接拉取;私有项目则需要被添加为成员才能拉取。实际交付时我会根据团队协作方式决定是否公开。
5.2 日志与目录结构:出了问题知道去哪看
Harbor 的数据目录结构值得提前熟悉,排查问题时能直接定位。以默认/data为例:
| 目录 | 内容 | 故障时关注点 |
|---|---|---|
/data/database | PostgreSQL 数据文件 | 空间占用大,备份时重点关照 |
/data/registry | 镜像存储层 | 磁盘增长主要来自这里 |
/data/redis | Redis 持久化数据 | 缓存和 session 数据 |
/data/log | 各组件日志 | 排错第一站 |
/data/secret | 证书和密钥 | prepare 生成,误删要重新生成 |
查看某个组件日志用docker compose logs:
cd /data/harbor && docker compose logs --tail=200 harbor-coreharbor-core是 Harbor 的业务核心,登录失败、权限问题、API 异常都能在这里看到具体堆栈。harbor-registry的日志则更多关注镜像上传下载的请求,推送慢时看这里最直接。
5.3 升级前的备份习惯
Harbor 从 v2.8.2 往上走升级包时,官方脚本会先拉起 migrator 容器做数据库迁移,但脚本不会帮你备份。我的习惯是先备份再升级,至少要把配置文件和数据库打出来。
cd /data/harbor cp harbor.yml harbor.yml.bak docker exec harbor-db pg_dump -U postgres harbor > harbor_db_$(date +%F).sqlpg_dump生成 SQL 格式的数据库备份,后面接+%F生成形如harbor_db_2025-01-15.sql的日期文件。升级失败时,用这份备份配合旧版本离线包就能回滚。配置文件里包含 hostname、密码、证书路径等关键信息,升级后如果配置格式有变化,harbor.yml.bak是找回原参数的最佳参照。
6. 进阶:把 GC 和备份做成一个定时任务
Harbor 跑起来之后最容易被忽略的是定期垃圾回收和数据库备份。镜像频繁推拉会在 registry 里留下大量未被引用的层,不清理磁盘会持续膨胀;数据库不备份,一次误删项目就后悔莫及。我习惯把这两个动作写成一个脚本,用 crontab 定时执行。
#!/bin/bash HARBOR_ADDR="192.168.10.20:8080" ADMIN="admin" PASS="YourStrongPass123" BACKUP_DIR="/backup/harbor" DATE=$(date +%F) curl -u "$ADMIN:$PASS" -X POST \ "http://$HARBOR_ADDR/api/v2.0/system/gc/schedule" \ -H "Content-Type: application/json" \ -d '{"schedule":{"type":"Manual"},"parameters":{"delete_untagged":true}}' docker exec harbor-db pg_dump -U postgres harbor > "$BACKUP_DIR/harbor_db_$DATE.sql" tar -czf "$BACKUP_DIR/harbor_cfg_$DATE.tgz" /data/harbor/harbor.yml find "$BACKUP_DIR" -mtime +14 -delete脚本第一段触发一次垃圾回收,delete_untagged设为 true,会清理掉所有未被 tag 引用的镜像层,这是回收空间的关键参数。第二段把 PostgreSQL 数据导出成 SQL 文件,第三段打包配置文件,最后删除 14 天前的旧备份,防止备份目录把自己所在磁盘也吃满。GC 触发后是异步执行的,需要到 Web 界面的「注册表」->「垃圾回收」页查看执行进度,脚本只负责提交任务。
定时任务放进 crontab:
30 2 * * * /usr/local/bin/harbor_backup.sh >> /var/log/harbor_backup.log 2>&1每天凌晨 2:30 执行,日志写入专门文件,方便第二天核查是否成功。我第一次在 ARM 设备上部署 Harbor 时,因为没配定时备份,一次误删项目导致整个 registry 数据回滚了几小时。从那以后,每次交付我都强制走一遍环境检查、写备份脚本、验证推送拉取链路,三件事做完才敢把仓库地址交给团队。希望帮到你。
本文还有配套的精品资源,点击获取