简介Harbor-offline-installer-v2.5.5-arm64.tgz 是一份面向 ARM64 架构的 Harbor 镜像仓库离线安装包专为内网或受限网络环境设计适合运维工程师和 DevOps 人员快速搭建私有容器镜像服务。整个压缩包共 24 个文件以 env、yml、conf 等配置类文件为主辅以 sh 脚本、tmpl 模板和 prepare 准备文件覆盖部署前配置、编排启动和初始化检查等环节包体约 531.33MB。目前已有 206 人浏览学习对于需要离线交付 Harbor 的场景有一定参考价值。包内包含 docker-compose.yml、harbor.yml.tmpl、common.sh、install.sh 等关键组件用户可根据实际情况修改模板并运行安装脚本省去逐一准备依赖的步骤尤其适合无公网拉取条件的生产环境。1. 为什么 harbor-offline-installer-v2.5.5-arm64.tgz 值得你花半小时看完如果你手上正好有一个 harbor-offline-installer-v2.5.5-arm64.tgz面前又是一台只能内网访问的 ARM64 服务器飞腾、鲲鹏都算这篇就是给你写的。典型场景银河麒麟 V10没有外网通道却要搭容器镜像仓库让交付和测试都能从这里拉镜像。文件名已回答了一切harbor 是仓库offline-installer 表示镜像与脚本全在包里v2.5.5 是版本arm64 说明它只认 aarch64 架构。这类包解决的是最典型的痛点没有 Docker Hub、没有公网 registry、不允许现场源码编译全靠一个 tgz 把仓库从零拉起来。它适合两种人第一次在国产 ARM 服务器上搭 Harbor 的运维照着命令能跑通搭过 x86 版、这次换架构翻车的熟手直接看第 4 章。先给一个反直觉的结论这个包最容易出问题的地方不在 Harbor 本身在宿主机 Docker 和 docker-compose 是否真的匹配 ARM64。后面所有操作都建立在这个前提上。2. 动手前先看懂离线包环境检查与三个选型判断拿到 tgz 直接解压、直接跑 ./install.sh是新手最常见的动作也是现场翻车的第一来源。我一般会先花十分钟做三件事确认包里有什么、确认宿主机是什么架构、确认 Docker 与 docker-compose 能不能被 Harbor 调用。这三件事跑完后面基本是流水账跑不完就动手后面每一条报错都在替你交学费。2.1 离线安装器里有什么tgz 解压后的四样东西先用tar -tzf预览而不是直接解压这是对离线包最基本的尊重。-t只读文件清单不落地能顺便确认包没在传输过程中损坏如果某个大文件在中途被截断tar会在这里就报错比装到一半再失败省事得多。tar -tzf harbor-offline-installer-v2.5.5-arm64.tgz # 只列文件清单校验包是否完整 tar -xzf harbor-offline-installer-v2.5.5-arm64.tgz # 真正解压 cd harbor ls -lh # 看每个文件的体积与权限-z告诉 tar 先做 gzip 解压-x才是落地。解压后一般是一个 harbor/ 目录里面最核心的东西有四类安装脚本、配置模板、镜像归档和一个公共库。文件作用要不要动install.sh安装入口负责加载镜像、调 prepare、起服务不动prepare配置生成器读 harbor.yml 生成 docker-compose.yml不动harbor.yml.tmpl配置模板安装前必须复制成 harbor.yml复制后改harbor.v2.5.5.tar.gz镜像归档包含 nginx、registry、core、db 等全部 arm64 镜像只读common.shinstall.sh 的公共函数做版本检查和环境探测不动关键点真正“离线”的部分是那个镜像归档。install.sh 在启动服务前会把里面的镜像 docker load 进本机 Docker所以安装失败时先盯 docker load 的输出而不是急着去翻 Harbor 组件日志。另一件容易被忽略的事包名里的 arm64 是整套镜像的架构前缀x86 机器跑它registry 容器一启动就会以 exec format error 退出这个在第 4 章展开。2.2 ARM64 宿主机检查清单CPU、内核、Docker 三者缺一不可ARM64 这个叫法来自 Debian 系内核和 Docker 里对应的词是 aarch64。飞腾、鲲鹏、麒麟 990 这些芯片在 Linux 下uname -m输出的就是 aarch64看到这个输出包名里的 arm64 才对得上号。uname -m # 期望输出 aarch64 / arm64 lscpu | grep -E ^(Architecture|Model name|CPU\(s\)) # 看 CPU 型号与核数 cat /etc/os-release # 确认发行版麒麟 V10、Ubuntu 22.04、CentOS 7 df -h / # 系统盘剩余空间至少留 20GB 给离线包和镜像 free -g # 内存建议 ≥ 4GB 可用每一条都有明确期望值。Harbor 官方给的最低要求是 2 核 4GB但实际跑起来PostgreSQL、redis、registry、core、jobservice 常驻就好几个进程我一般按 4 核 8GB 起机器后面如果要开 Trivy 漏洞扫描内存再往上加。磁盘要看两个地方系统盘要能装下离线包解压后的体积外加 docker load 产生的临时层数据卷另算别把仓库数据放在根分区。宿主机发行版的选择直接影响踩坑概率。银河麒麟 V10 上通常自带 19.03 左右的 Docker 编译版和 Harbor 配合最顺Ubuntu 22.04 ARM64 用官方 apt 源装 Docker 也干净最难受的是 CentOS 7 ARM内核停在 3.10Docker 存储驱动可能自动降级到 vfs性能差而且某些内核模块和 Harbor 的容器网络对不上。能选新内核就别在 3.10 上硬扛。2.3 docker 与 docker-compose 的版本红线x64 的 compose 在 ARM 上直接翻车Harbor 2.5.5 的官方要求是 Docker 17.06 以上、docker-compose 1.18 以上但实践里真正卡人的不是版本号而是“docker-compose 这个命令到底存不存在、架构对不对”。install.sh 内部执行的是 docker-compose 而不是 docker compose所以 compose plugin 或者独立二进制必须能以 docker-compose 这个名字出现在 PATH 里。docker version --format Server: {{.Server.Version}} / {{.Server.Arch}} docker-compose --version # 必须能打印版本且不报 exec format error which docker-compose # 确认 PATH 里能找到判定逻辑很简单第一条命令里 Server.Arch 必须是 aarch64 或者 arm64如果在 ARM 机器上显示 x86_64说明 docker 包本身就装错了架构第二条命令报 exec format error说明 docker-compose 二进制是从 x64 机器拷过来的——这是飞腾机器上最常见的低级翻车。docker-compose 的 arm64 二进制可以从官方 Release 页面拿到或者在有网的机器上下好后用 U 盘带进内网麒麟软件源里有时也有打包好的版本能用仓库装就别手动拷。装完别急着跑 install.sh先执行一次docker-compose config验证语法。这一步只解析配置不启容器能在五分钟内暴露 compose 二进制损坏、PATH 不对、依赖缺失三类问题。注意Harbor 2.5.5 的 install.sh 只认 docker-compose 命令。没有这个命令安装脚本会在最开始就退出所有后续排查都是浪费时间。3. 最小命令从解压到跑通install.sh 全流程复现前面的检查都过了这一章就是把 tgz 变成可用仓库的完整命令序列。我按最典型的纯内网、HTTP、独立数据卷场景来写如果你要开 HTTPS 或者加 Trivy先把第 4 章的相关内容看完再决定别到时候反复卸载重装。3.1 解压与生成配置先体检再落地进入正题。第一步还是先预览再解压和第 2 章的区别是这次要直接落地因为后面所有操作都依赖这个目录。tar -tzf harbor-offline-installer-v2.5.5-arm64.tgz # 回显文件清单相当于完整性体检 tar -xzf harbor-offline-installer-v2.5.5-arm64.tgz cd harbor cp harbor.yml.tmpl harbor.yml # install.sh 只认 harbor.yml grep -v ^\s*# harbor.yml | grep -v ^\s*$ # 看有效配置行确认模板没损坏cp这一步是复制的不要用软链。后续 prepare 会重新读 harbor.yml 并生成一套配置模板在每次安装时都会被复写历史改动只保留在你自己的备份里。grep -v两条管道是把注释和空行过滤掉如果输出为空说明模板文件是坏的常见原因是压缩包在传输中被截断回到tar -tzf看是不是在某个大文件处中断。模板本身带着大量注释每个字段都写了说明对新手友好但也是坑注释行太多改错缩进不容易一眼看出来。3.2 harbor.yml 必调项hostname、端口、密码、数据目录harbor.yml 里字段不少但第一次安装真正要动的只有四个。其余保持模板默认值即可动多了反而增加排障负担。# harbor.yml 关键段落用空格缩进不要用 tab hostname: 10.10.1.50 # 其他节点用来访问的地址写内网 IP 或内网域名 http: port: 8080 # 默认 80被 nginx 占用就改成 8080 harbor_admin_password: YourPassw0rd # 首次登录 admin 的密码 data_volume: /data/harbor # 放到独立数据盘别放系统根分区 log: level: info # 排障时才临时改 debug database: password: change-me # 模板里有默认值内网生产环境建议一并改掉hostname 是这条配置里最重要的一项。它决定了两件事Harbor 生成的服务地址以及客户端 docker push/pull 时要拼的镜像前缀。如果你写 localhost其他机器拿内网 IP 登录就会 401写 IP以后换 IP 又要改配置重装。内网环境我一般直接写 IP省掉 DNS 的环节。http.port 默认 80很多机器上 80 已被系统自带的 nginx 占用改成 8080 最省事代价是客户端 docker login 时要把端口写全。harbor_admin_password 强度至少八位别用模板里的默认口令现在很多扫描脚本在扫弱口令。data_volume 是数据卷根目录Harbor 的项目数据、镜像 blob、数据库文件、密钥全在下面建议单独一块盘。改完缩进后用 3.1 的 grep 命令再自查一遍yaml 报错是 prepare 阶段最常见的失败原因报错信息通常直接告诉你第几行缩进错了。3.3 执行 install.sh 与第一次健康检查三个验证命令配置改完剩下的交给脚本。install.sh 的执行顺序是prepare 生成配置 → docker load 导入镜像 → docker-compose up 拉起服务。离线包的好处在这一步体现得最明显全程不需要外网docker load 把镜像从归档灌进本机 Docker 后所有容器都是本地启动。sudo ./install.sh # 全流程prepare → docker load → docker-compose up -d # 首次安装先别加 --with-trivy看完第 4 章再说 docker-compose ps # 核心容器应全部为 Up curl -I -m 5 http://10.10.1.50:8080/api/v2.0/systeminfo curl -s -u admin:YourPassw0rd http://10.10.1.50:8080/api/v2.0/systeminfo | head -c 300docker-compose ps 里应该看到 9 个核心容器全部 Upnginx、harbor-core、harbor-db、harbor-jobservice、harbor-log、harbor-portal、harbor-registry、harbor-registryctl、harbor-redis。只要有一个是 Restarting 或者 Exited先docker-compose logs --tail100看它为什么退不要盲目 restart大概率是配置或架构问题。curl 第一条用 -I 只拿响应头-m 5 控制超时第二条带账号密码打 systeminfo 接口返回的 JSON 里 version 字段是 2.5.5说明服务真正起来了。浏览器打开 8080 端口能进登录页就算过。提示首次 docker load 在飞腾这类机器上可能跑十几分钟磁盘 IO 重别因为慢就 CtrlC。中断后重跑 install.sh 是安全的但先docker-compose down再跑更干净。4. ARM64 离线部署避坑实录五个高频翻车现场的现象、原因与处置以下五条按发生频率排全部来自 x86 经验迁移到 ARM 架构后最容易翻车的点。每条按“现象 → 原因 → 处置”写处置给的是能直接抄的命令。4.1 现象install.sh 报 docker-compose: command not found现象./install.sh 运行几秒就退出输出里明确写着 command not found。原因机器上只有 docker 没有 docker-compose或者装了 compose plugin 但命令名对不上。处置docker compose version # 确认 compose plugin 是否存在v2 系列 # 没有独立二进制时在有网的机器下载 linux-aarch64 版 docker-compose 后拷入内网 sudo install -m 755 docker-compose-linux-aarch64 /usr/local/bin/docker-compose docker-compose --version # 验证能打印版本install.sh 调的是老接口它不管你是 compose v1 还是 v2只看 PATH 里有没有 docker-compose 这个名字。所以最简单可靠的做法是准备一个 aarch64 的独立二进制放在 /usr/local/bin 下。注意别从 x64 机器上拷第 2 章的红线在这里生效拷过来就是 exec format error。4.2 现象docker load 报错或 registry 容器反复重启日志里全是 exec format error现象install.sh 在 docker load 阶段报错或者镜像明明加载成功docker-compose ps 里 harbor-registry 反复 Restartingdocker logs 一翻全是 exec format error。原因把 x64 的 harbor-offline-installer-v2.5.5.tgz 直接拷到了 ARM 机器上或者 docker-compose 本身是 x64 二进制。这是离线包分发里最隐蔽的坑两个文件名字长得几乎一样只差一个 arm64 后缀。docker images | grep -E goharbor|harbor # 看镜像列表是否为空或架构异常 docker inspect harbor-registry --format {{.Architecture}} # 单镜像确认架构 docker logs harbor-registry --tail 50 # 出现 exec format error 即判定架构不匹配 uname -m # 再确认一次宿主机架构docker inspect 输出的 Architecture 如果是 amd64镜像和宿主机对不上容器起不来是必然的。处置动作只有一个重新拿 arm64 包而不是在机器上装 qemu 硬跑。生产环境不接受“模拟器保平安”的路数架构不匹配就要从源头解决。另外提醒一句网上一堆 CentOS 7 搭 Harbor 的教程都是 x86_64 的ARM 上能选内核新的系统就别选 3.10。4.3 现象Web 能登录客户端 push 报 HTTP/HTTPS mismatch 或 401现象浏览器能打开 8080 并登录但在其他服务器上 docker login 报错要么是“http: server gave HTTP response to HTTPS client”要么直接 401。原因分两半客户端 docker 默认走 HTTPS内网 Harbor 是 HTTP需要把仓库地址加进 insecure-registries 白名单401 则多半是密码错误或者 hostname 和登录地址不一致。处置在客户端机器上执行sudo tee /etc/docker/daemon.json EOF { insecure-registries: [10.10.1.50:8080] } EOF sudo systemctl daemon-reload sudo systemctl restart docker docker login 10.10.1.50:8080 -u admin -p YourPassw0rdinsecure-registries 是数组多个仓库用逗号分隔。改完必须重启 docker这一步是最容易被忽略的很多人改完不重启报错原封不动。服务端侧如果改过 harbor.yml 的 hostname 而没重跑 install.sh也会出现 401改配置后必须重新执行一次安装脚本或者至少跑 prepare 再 docker-compose up -d。4.4 现象加上 --with-trivy 后 trivy-adapter 反复重启现象./install.sh --with-trivy 跑完后trivy-adapter 容器一直 RestartingWeb 界面扫描漏洞永远没结果。原因Trivy 第一次启动要在线拉漏洞库纯内网必然失败而且某些 ARM 机型内存小扫描时容器直接被 OOM 杀掉。处置docker-compose ps | grep trivy # 确认是不是 Restarting 状态 docker logs trivy-adapter --tail 50 # 找 network、unsupported、killed 等关键字 free -g # 看内存余量如果确实需要漏洞扫描能力得在有网环境提前准备离线漏洞库文件拷进内网后配置 Trivy 的离线数据路径具体挂载位置随版本有差异按官方离线安装说明操作。否则就不要开 --with-trivyHarbor 的核心能力——存镜像、复制、项目权限——完全不受影响。Notary 同理纯内网没有外部的签名信任链默认不开最省心。4.5 现象数据卷写满GC 之后空间不回现象跑了几个月/data 或系统盘 100%执行 garbage-collect 后 df 发现空间没怎么回来。原因GC 只回收 registry 内部标记为删除的层正被引用或复制中的 blob 不动更常见的是 data_volume 压根没挪镜像全压在系统盘上docker 自身的 overlay2 也占同一块盘。处置du -sh /data/harbor/* | sort -h # 找出数据卷里的大头 docker system df # 区分镜像缓存和容器层占用 # 低峰期执行有复制任务时别做 docker-compose exec registry registry garbage-collect --dry-run /etc/registry/config.yml先 --dry-run 看要回收多少确认数量正常再正式跑。默认配置里回收站还会保留一段时间空间真正的释放要等清理回收站之后。生产建议是把 data_volume 放到独立磁盘GC 在低峰期做做完重启 registry 容器让空间统计刷新。记住一条GC 不是磁盘快满时的后悔药它是定期维护动作。注意不要在复制任务进行中执行 GC否则远端仓库重新拉取时会发现层被标记删除导致复制失败。5. 装完不是结束离线环境的数据导入、备份与版本升级Harbor 起来只是开始。内网环境的真正难题在后续镜像怎么进来、数据丢了怎么恢复、版本怎么升。这一章把这三年问题一次说清。5.1 离线镜像怎么进 Harborsave/load/tag/push 三件套纯内网没有外网镜像入库最可靠的手工链路是在有网的机器上 pull 好镜像并 docker save打包带回内网在 Harbor 所在机器 docker load然后 tag 和 push。这条链路的好处是全程不依赖 Harbor 的复制功能可控性最强。# 源机器上按清单批量 pull 并 save while read -r img; do fname$(echo $img | tr /: __).tar docker pull $img docker save $img -o $fname done images.txt文件名里的斜杠和冒号用 tr 替换成下划线避免生成嵌套目录这个细节在批量操作时能省掉很多麻烦。注意一个关键问题源机器如果是 x86pull 下来的就是 amd64 镜像导入 ARM 的 Harbor 后能存但客户端拉到 ARM 节点上跑不起来。要么源头保证镜像支持多架构要么在 ARM 机器上完成 pull 和 save。# Harbor 所在机器load、tag、push 一个具体例子 docker load -i nginx_1.25.3.tar docker tag nginx:1.25.3 10.10.1.50:8080/library/nginx:1.25.3 docker push 10.10.1.50:8080/library/nginx:1.25.3push 之前必须先 docker login否则会 401。library 是 Harbor 默认的公开项目私有项目需要先在 Web 界面创建好再推到对应项目名下。镜像一多建议写成脚本把 images.txt 里的清单循环处理避免手滑。5.2 备份什么才算完整数据库、/data、配置三件套很多人只备份 harbor.yml 甚至 docker-compose.yml恢复的时候才发现项目、账号、复制规则全没了。Harbor 的完整备份是三件套数据库、数据卷、配置文件。docker exec harbor-db pg_dump -U postgres -d registry registry-$(date %F).sql docker-compose stop # SQL 落盘后再停服务保证 /data 与 SQL 时间点一致 sudo tar -czf harbor-data-$(date %F).tgz -C /data harbor cp harbor.yml harbor.yml.bak-$(date %F) docker-compose start顺序有讲究先 pg_dump再停服务然后打包 /data。如果先停服务再 dump数据库容器也跟着停了exec 进不去如果不停服务直接打包 /data镜像 blob 可能正在被写入备份不一致。tar 打包时把整个 harbor 数据卷都带走包括 secret 目录丢了它恢复后组件之间会验签失败。备份项内容漏掉会怎样PostgreSQL 数据项目、用户、复制规则、标签账号项目全丢/data/harbor镜像 blob、secret、数据库文件镜像与密钥不可恢复harbor.yml端口、密码、数据卷路径配置靠猜恢复的思路是先装同版本 Harbor停服务把三件套覆盖回原位再跑一次 ./install.sh。恢复之前先验证 SQL 文件和 tgz 都能解压别等宕机了才发现备份文件是坏的。5.3 从 v2.5.5 升到新版两个必做动作和一个原则升级不是解压新包跑 install.sh 就完事。Harbor 跨版本时数据库结构会变升级的本质是迁移而迁移的前提是备份。两个必做动作先做 5.2 的三件套备份再做新旧模板的字段对比。一个原则按版本路径逐级升别从 2.5.5 一步跨到 3.x跨太多版本时迁移脚本可能不认。cd /opt/harbor # 当前 2.5.5 安装目录 docker-compose down # 停全套服务容器删掉但 /data 和 harbor.yml 保留 # 解压新版本离线包到新目录 mkdir -p /opt/harbor-upgrade tar -xzf harbor-offline-installer-v新版-arm64.tgz -C /opt/harbor-upgrade # 把旧 harbor.yml 覆盖到新目录先 diff 新旧模板确认新增字段 cp /opt/harbor/harbor.yml /opt/harbor-upgrade/harbor/ cd /opt/harbor-upgrade/harbor sudo ./install.sh新版 install.sh 启动时会检测到数据卷里已有旧版本数据自动执行数据库迁移日志里会出现 migration 相关输出。这时候最忌讳的是删掉 /data 重来删了等于放弃所有历史数据。模板 diff 那步别省新版本如果加了必填字段旧配置直接跑会报错先把字段补上再执行安装。6. 给 x86 开发机准备的预演用 qemu 在本地把 ARM64 离线包体检一遍ARM 服务器贵、排队、不好随便折腾x86 笔记本上能不能先把离线包验一遍能靠 qemu 的用户态模拟加 docker 的 --platform 参数。做法是先用 qemu-user-static 注册 binfmt让 docker 在 x86 宿主机上能跑 arm64 容器然后把离线包挂进容器里做静态体检。# 一次性注册 binfmt让 docker 能在 x86 上运行 arm64 容器 docker run --rm --privileged multiarch/qemu-user-static --reset -p yes # 把离线包挂进 arm64 容器做解压与脚本体检 docker run --rm --platform linux/arm64 \ -v $PWD/harbor-offline-installer-v2.5.5-arm64.tgz:/pkg.tgz \ ubuntu:22.04 /bin/bash -c cd /tmp tar -tzf /pkg.tgz /tmp/list.txt || exit 1 tar -xzf /pkg.tgz cd harbor bash -n install.sh echo install.sh syntax OK grep -c arm64\|aarch64 list.txt echo manifest OK --privileged 是给 qemu-user-static 写 binfmt_misc 注册表用的注册完同一台机器上没必要再开这个权限跑别的容器--platform linux/arm64 强制按 arm64 架构拉镜像和创建容器Ubuntu 22.04 是多架构镜像所以拉得下来。bash -n 只做语法检查不执行脚本能发现 install.sh 的换行符、权限、路径问题。6.1 能体检什么不能体检什么这套预演能抓的问题很明确包在传输中损坏、文件清单不完整、脚本语法错误、镜像清单缺失。不能抓的也很明确真实磁盘 IO、内核存储驱动、内存占用、网络互通——这些只能在真机上做验收。所以别指望 qemu 预演替代真机测试它的价值是把“包与架构不匹配”这类低级错误挡在机房门外。还有一个实用技巧预演时把解压后的目录打一个 baseline 包记下 sha256到现场解压后对比一次能确认分发过程没有二次损坏。多台同构机器部署时这个基线能省掉逐台检查的功夫。我现在的习惯是拿到任何带架构后缀的离线安装包第一件事就是在笔记本上用 qemu 起一个同架构容器做静态体检确认包没坏、脚本能解析再预约现场时间。这个习惯帮我省掉了至少两次白跑机房。预演当然不能替代真机但它把最容易翻车的环节提前排掉了——希望帮到你。本文还有配套的精品资源点击获取