☰
arm架构离线安装harbor-v2.9.0:鲲鹏服务器实战避坑指南
2026/10/13 4:07:33 网站建设 项目流程

简介:面向需要在国产化或 ARM 服务器上私有化部署容器镜像仓库的运维与 DevOps 人员,这份资源提供 harbor-v2.9.0 的 arm64 架构离线安装包,解决内网环境无法拉取镜像、x86 安装包不兼容等痛点。压缩包共 6 个文件,以 sh 脚本、gz 归档、license 授权文件、prepare 预处理脚本与 tmpl 配置模板为主,整体约 722.35MB,覆盖安装脚本、离线镜像归档与配置样例,解压后执行 install.sh 即可一键完成部署,前置条件为已安装 docker 与 docker-compose。目前已有 962 人学习下载,适合具备一定 Linux 与容器基础、希望快速搭建企业级镜像仓库的中高级用户。借助该包可省去逐层拉取镜像与手工配置的繁琐流程,直接获得可运行的 Harbor 服务,并参考配套文档完成参数调整与故障排查,显著缩短私有仓库的落地周期。

1. 从一台断网的鲲鹏服务器说起:harbor-v2.9.0 离线安装(arm架构)到底难在哪

上周有台鲲鹏 920 的服务器,机房在内网深处,连个 yum 源都摸不到,却要我把 harbor-v2.9.0 部署上去当镜像仓库。x86 上装 Harbor 我闭着眼都能敲,但 arm架构 加上完全离线,情况就完全不一样了。harbor 官方提供的离线安装包默认只覆盖 amd64,arm64 的镜像得自己找或者自己构建,docker 和 docker-compose 的二进制也得换成 aarch64 版本。更麻烦的是,harbor 依赖的 PostgreSQL、Redis、Nginx 这些组件在离线包里都是容器镜像,一旦某个镜像的 arm64 版本缺失,整个安装就会卡在docker pull那一步,而内网环境连报错都报得含糊。这篇文章就是把我踩过的坑和最终跑通的路径完整拆开,从环境准备、离线包制作、配置修改到启动排错,每一步都给出可复现的命令和参数。如果你手里也有一台不能上网的 arm 服务器,想把它变成团队的私有镜像仓库,下面的内容可以直接抄作业。

2. 离线安装前必须锁死的四个环境前提

2.1 确认 CPU 架构和操作系统版本

arm架构 不是一句「我是 arm」就能糊弄过去的。鲲鹏 920、飞腾 2000、Ampere Altra 虽然都是 aarch64,但内核版本和 glibc 版本差异会直接影响 docker 的二进制兼容性。我一般先跑这三条命令把底摸清:

uname -m # 输出 aarch64 才继续,armv7l 是 32 位,harbor-v2.9.0 不支持 cat /etc/os-release # 重点看 VERSION_ID,麒麟 V10、openEuler 20.03、CentOS 7.9 的包管理方式不同 ldd --version | head -1 # glibc 版本低于 2.17 的,docker 静态二进制可能跑不起来

uname -m返回aarch64是硬性门槛,如果返回armv7l说明是 32 位系统,harbor 的镜像根本没有对应的 manifest,不用往下试了。/etc/os-release里的ID和VERSION_ID决定了你后续装 docker 是用 rpm 还是 deb,也决定了 systemd 的版本能不能支持 harbor 的 service 文件。glibc 版本这条容易被忽略,但我在 openEuler 20.03 上遇到过 docker 二进制依赖libc.so.6符号缺失的情况,最后换了静态编译版本才解决。

2.2 离线安装 docker 与 docker-compose 的 arm64 版本

harbor-v2.9.0 的安装脚本依赖 docker 和 docker-compose,这两个在离线环境下必须提前准备好 arm64 的二进制。docker 官方静态二进制包在https://download.docker.com/linux/static/stable/aarch64/下有,但内网拿不到,需要在一台能上网的机器上下载后拷进去。docker-compose 更麻烦,v2 版本是 Go 编译的单文件,直接下docker-compose-linux-aarch64就行。

# 在有网的机器上执行,下载后通过 U 盘或内网传输拷到目标服务器 wget https://download.docker.com/linux/static/stable/aarch64/docker-24.0.7.tgz wget https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-aarch64 # 目标服务器上解压安装 tar -xzvf docker-24.0.7.tgz cp docker/* /usr/local/bin/ chmod +x /usr/local/bin/docker* cp docker-compose-linux-aarch64 /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose # 配置 systemd 管理 docker cat > /etc/systemd/system/docker.service <<'EOF' [Unit] Description=Docker Application Container Engine After=network-online.target firewalld.service Wants=network-online.target [Service] Type=notify ExecStart=/usr/local/bin/dockerd ExecReload=/bin/kill -s HUP $MAINPID LimitNOFILE=infinity LimitNPROC=infinity TimeoutStartSec=0 Delegate=yes KillMode=process Restart=on-failure StartLimitBurst=3 StartLimitInterval=60s [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable docker --now docker info | grep -i architecture # 确认输出 aarch64

这里 docker 版本我选的是 24.0.7,因为 harbor-v2.9.0 的 compose 文件里对 docker API 版本有要求,太老的 docker 会报client version too old。docker-compose用的是 v2.23.0,单文件二进制,不依赖 Python 环境,比 v1 省心很多。systemd 文件里ExecStart指向/usr/local/bin/dockerd,如果你把二进制放在别处要对应改。启动后docker info里的Architecture字段必须是aarch64,如果是x86_64说明你拷错了包。

2.3 准备 harbor-v2.9.0 的 arm64 离线包

harbor 官方 release 页面提供的harbor-offline-installer-v2.9.0.tgz里面包含的是 amd64 镜像,直接拿到 arm 上用会报no matching manifest for linux/arm64。我的做法是分两步:先下载官方离线包拿到harbor.yml模板和安装脚本,再单独准备 arm64 的镜像包。

# 在有网机器上下载官方离线包 wget https://github.com/goharbor/harbor/releases/download/v2.9.0/harbor-offline-installer-v2.9.0.tgz tar -xzvf harbor-offline-installer-v2.9.0.tgz # 解压后得到 harbor/ 目录,里面有 harbor.yml.tmpl、install.sh、prepare # 查看官方包里镜像的架构,确认是 amd64 tar -tzf harbor.v2.9.0.tar.gz | head -5 # 如果输出里有 amd64 字样,说明这个包不能直接用

官方离线包里的harbor.v2.9.0.tar.gz是镜像归档,但架构不对。arm64 的镜像需要从 harbor 的官方 registry 拉取后重新打包,或者找社区构建好的 arm64 版本。我一般用docker pull --platform linux/arm64在一台 arm 机器上把 harbor 所需的九个镜像全部拉下来,然后docker save成一个 tar 包。这九个镜像包括harbor-core、harbor-portal、harbor-jobservice、harbor-registry、harbor-registryctl、harbor-db、harbor-redis、harbor-trivy、nginx。少一个,install.sh执行到docker load那步就会断。

2.4 内核参数与防火墙的预检清单

harbor 跑起来需要一些内核参数配合,离线环境下这些参数不会自动配好。我整理了一个预检清单,装之前逐条过一遍:

检查项命令期望值
桥接流量转发sysctl net.bridge.bridge-nf-call-iptables1
IP 转发sysctl net.ipv4.ip_forward1
文件句柄数ulimit -n65536 以上
防火墙 80/443 端口firewall-cmd --list-ports放行或关闭防火墙
SELinuxgetenforcePermissive 或 Disabled

net.bridge.bridge-nf-call-iptables如果返回 0,容器之间的网络通信会出玄学问题,harbor 的 portal 能打开但 core 服务连不上 db。ulimit -n太小的话,镜像推拉多了会报too many open files。SELinux 在麒麟系统上默认是 enforcing,不关掉的话 docker 挂载目录会 permission denied,这个坑我踩过两次,血泪经验就是装之前先setenforce 0。

3. 从零跑通 harbor-v2.9.0 离线安装的完整命令链

3.1 解压离线包与目录规划

把前面准备好的 harbor 离线包和 arm64 镜像 tar 包传到目标服务器,我习惯放在/opt/harbor-install下,避免和系统目录混在一起。

mkdir -p /opt/harbor-install cd /opt/harbor-install # 解压官方离线包,拿到配置模板和脚本 tar -xzvf harbor-offline-installer-v2.9.0.tgz cd harbor # 把 arm64 镜像包放到 harbor 目录下,替换掉原来的 amd64 包 mv /opt/harbor-install/harbor.v2.9.0-arm64.tar.gz ./harbor.v2.9.0.tar.gz # 确认目录结构 ls -lh # 应该看到 harbor.v2.9.0.tar.gz、harbor.yml.tmpl、install.sh、prepare

这里有个细节:官方包解压后harbor.v2.9.0.tar.gz是 amd64 的,我直接用 arm64 的包覆盖了同名文件。install.sh脚本里写死了加载harbor.v2.9.0.tar.gz,所以文件名必须一致,不能改成别的。prepare脚本会检查harbor.yml是否存在,不存在就从harbor.yml.tmpl复制一份,这个逻辑在离线环境下没问题。

3.2 改写 harbor.yml 的五个关键参数

harbor.yml.tmpl里有几十个配置项,但离线 arm 环境下真正需要改的就五个。我一般先复制一份再改:

cp harbor.yml.tmpl harbor.yml vim harbor.yml
# 1. hostname 改成服务器的 IP 或域名,不要用 localhost hostname: 192.168.1.100 # 2. http 端口,如果 80 被占用改成其他端口 http: port: 80 # 3. https 先注释掉,离线环境没有证书,配了反而起不来 # https: # port: 443 # certificate: /your/certificate/path # private_key: /your/private/key/path # 4. harbor_admin_password 改成强密码 harbor_admin_password: Harbor12345 # 5. data_volume 指定数据盘路径,别用默认的 /data data_volume: /opt/harbor-data # 6. database 的 password 也要改,默认是 root123 database: password: root123 max_idle_conns: 100 max_open_conns: 900

hostname这一项如果填localhost或127.0.0.1,docker 客户端在其他机器上推镜像时会报no such host,必须填一个能解析的 IP 或域名。https部分在离线环境没有证书的情况下直接注释掉,harbor 会只跑 http,虽然不安全但内网能用。data_volume默认是/data,如果系统盘小,一定要改到大盘上,否则镜像多了会把根分区撑爆。database.password和harbor_admin_password是两个不同的密码,前者是 PostgreSQL 的,后者是 harbor 登录密码,别搞混。

3.3 执行 install.sh 并观察容器启动顺序

配置改完后,跑install.sh之前先确认 docker 已经起来,然后执行:

./install.sh --with-trivy # 如果不需要镜像扫描,可以不加 --with-trivy,少拉一个镜像 # 安装过程会输出大量日志,重点看这几行 # [Step 0]: checking if docker is installed ... # [Step 1]: checking docker-compose is installed ... # [Step 2]: loading Harbor images ... # [Step 3]: preparing environment ... # [Step 4]: preparing harbor configs ... # [Step 5]: starting Harbor ...

install.sh会依次做五件事:检查 docker 和 docker-compose、加载镜像、生成配置、启动容器。加载镜像那一步如果卡住超过两分钟,大概率是 tar 包里的镜像架构不对,用docker images看有没有导入成功。启动容器后,docker-compose ps应该看到九个容器,状态都是Up或healthy。如果有容器是Exit状态,用docker-compose logs <服务名>看日志,最常见的是 db 初始化失败和 redis 连接超时。

3.4 验证 harbor 服务是否真正可用

容器都起来不代表 harbor 就能用,我一般按这个顺序验证:

# 1. 检查容器健康状态 docker-compose ps # 所有容器 State 应该是 Up (healthy),harbor-core 可能需要等 30 秒 # 2. 检查端口监听 ss -tlnp | grep -E '80|443' # 应该看到 docker-proxy 监听在 80 端口 # 3. 用 curl 访问 API curl -u admin:Harbor12345 http://192.168.1.100/api/v2.0/projects # 返回 JSON 数组说明 API 正常 # 4. 用 docker 客户端登录并推拉镜像 docker login 192.168.1.100 -u admin -p Harbor12345 docker pull nginx:alpine docker tag nginx:alpine 192.168.1.100/library/nginx:alpine docker push 192.168.1.100/library/nginx:alpine

docker-compose ps里harbor-core的健康检查有延迟,刚启动时显示starting是正常的,等半分钟再看。curl那一步如果返回 401,说明密码不对;返回 503 说明 core 还没起来。docker push是最真实的验证,能推上去说明 registry、core、db、redis 整条链路都通了。推完后去 harbor 的 web 界面刷新,能看到镜像列表才算彻底跑通。

4. arm架构离线安装 harbor 的五个翻车现场

4.1 镜像 manifest 不匹配:no matching manifest for linux/arm64

现象:install.sh执行到docker load时卡住,或者docker-compose up时报no matching manifest for linux/arm64 in the manifest list entries。

原因:离线包里的harbor.v2.9.0.tar.gz是 amd64 架构的镜像,arm 机器加载后无法运行。docker 在启动容器时会检查镜像的架构标签,不匹配就直接拒绝。

解决:在一台 arm 机器上用docker pull --platform linux/arm64把 harbor 所需的九个镜像全部拉下来,然后docker save -o harbor.v2.9.0.tar.gz <镜像列表>重新打包。注意docker save时要带上所有 tag,否则docker-compose找不到对应镜像。

4.2 docker-compose 版本过低导致 API 报错

现象:install.sh报ERROR: client version 1.41 is too old. Minimum supported API version is 1.44。

原因:harbor-v2.9.0 的docker-compose.yml里用了较新的 compose 语法,老版本的 docker-compose v1 或者 docker 版本低于 20.10 都会触发这个错误。

解决:把 docker 升级到 24.0.7 以上,docker-compose 换成 v2.23.0 的单文件二进制。注意 docker-compose v2 的命令是docker compose(中间有空格)还是docker-compose(连字符),harbor 的install.sh里用的是连字符形式,所以二进制文件名必须是docker-compose。

4.3 数据目录权限导致 PostgreSQL 启动失败

现象:harbor-db容器反复重启,日志里报initdb: could not create directory "/var/lib/postgresql/data": Permission denied。

原因:data_volume指定的目录在宿主机上不存在,或者权限不是 999:999(PostgreSQL 容器内的用户 UID)。docker 挂载宿主机目录时不会自动创建,需要手动建好并赋权。

解决:

mkdir -p /opt/harbor-data/database chown -R 999:999 /opt/harbor-data/database chmod 700 /opt/harbor-data/database

harbor-data下还有redis、registry、trivy等子目录,最好都按对应容器的 UID 赋权,省得一个个排错。

4.4 防火墙未放行导致 core 与 db 断连

现象:harbor 的 web 界面能打开,但登录时报Internal Server Error,harbor-core日志里大量dial tcp 172.18.0.3:5432: connect: connection refused。

原因:宿主机防火墙拦截了 docker 自定义网络(通常是172.18.0.0/16)的流量,导致容器之间无法通信。麒麟系统和 openEuler 默认的 firewalld 规则比较严格。

解决:要么关掉 firewalld,要么把 docker 网段加入信任区域:

firewall-cmd --permanent --zone=trusted --add-source=172.18.0.0/16 firewall-cmd --reload

更彻底的方式是改 docker 的daemon.json,把iptables设为false,但这样会失去端口映射的隔离,内网环境可以接受。

4.5 磁盘空间不足导致镜像加载中断

现象:docker load执行到一半报no space left on device,/var/lib/docker所在分区被撑满。

原因:harbor 的九个镜像解压后大约占 2.5GB,加上 docker 的存储驱动开销,实际需要 5GB 以上。如果/var/lib/docker在根分区且根分区只有 20GB,很容易爆。

解决:装之前用df -h /var/lib/docker确认可用空间大于 10GB。不够的话,改 docker 的># /etc/docker/daemon.json { "data-root": "/opt/docker-data", "exec-opts": ["native.cgroupdriver=systemd"] }

改完重启 docker,之前加载的镜像会丢,需要重新docker load。

5. 把 harbor 离线包做成可复用的内部资产

装完一台不算完,团队里还有三台 arm 服务器等着部署,每次重新拉镜像不现实。我的做法是把整个安装过程脚本化,做成一个自包含的离线包,拷到任何一台 arm 机器上都能一键跑通。这个包的结构是这样的:

harbor-arm64-offline/ ├── install.sh # 主安装脚本 ├── harbor/ │ ├── harbor.v2.9.0.tar.gz # arm64 镜像包 │ ├── harbor.yml # 预配置好的模板 │ └── install.sh # harbor 官方脚本 ├── docker/ │ ├── docker-24.0.7.tgz │ └── docker-compose-linux-aarch64 └── check.sh # 环境预检脚本

主安装脚本install.sh的逻辑是:先跑check.sh确认架构和内核参数,然后装 docker 和 docker-compose,接着解压 harbor 包、替换harbor.yml里的 hostname 和密码,最后执行./install.sh --with-trivy。关键代码片段:

#!/bin/bash set -e # 环境预检 ARCH=$(uname -m) if [ "$ARCH" != "aarch64" ]; then echo "ERROR: 当前架构 $ARCH 不是 aarch64,终止安装" exit 1 fi # 安装 docker if ! command -v docker &> /dev/null; then tar -xzvf docker/docker-24.0.7.tgz cp docker/* /usr/local/bin/ cp docker/docker-compose-linux-aarch64 /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker* # 配置 systemd 并启动 cp docker/docker.service /etc/systemd/system/ systemctl daemon-reload systemctl enable docker --now fi # 部署 harbor cd harbor HOSTNAME=${1:-192.168.1.100} sed -i "s/^hostname:.*/hostname: $HOSTNAME/" harbor.yml sed -i "s/^harbor_admin_password:.*/harbor_admin_password: ${HARBOR_PASSWORD:-Harbor12345}/" harbor.yml ./install.sh --with-trivy # 验证 sleep 10 docker-compose ps | grep -q "Up" && echo "Harbor 部署成功" || echo "Harbor 部署异常,请检查日志"

这个脚本里set -e保证任何一步失败就停,不会带着错误继续跑。HOSTNAME和HARBOR_PASSWORD通过环境变量传入,避免硬编码。sed替换harbor.yml时用了^hostname:锚定行首,防止误改注释里的内容。最后用docker-compose ps做一次粗验证,虽然不够严谨,但能挡住大部分低级错误。

验证方法上,我习惯在部署完后跑一个冒烟测试:推一个 10MB 左右的镜像上去,再拉下来,对比 sha256。这个操作能同时验证 registry 存储、core 鉴权、db 元数据写入三条链路。如果推拉都正常,基本可以放心交给团队用了。

最后说个我自己的习惯:每次离线部署完,我会把harbor.yml和docker-compose.yml备份到/opt/harbor-install/backup/下,文件名带上日期。因为 harbor 升级或者迁移时,这两个文件是后悔药,没有它们就得从头猜配置。arm架构 的离线安装尤其如此,环境差异大,记录好每一步的配置,下次遇到同类机器能省半天时间。希望帮到你。

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

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

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

立即咨询