ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

ARM服务器离线部署Harbor 2.4.0:从镜像适配到运维避坑实战

ARM服务器离线部署Harbor 2.4.0:从镜像适配到运维避坑实战

简介:本资源为 Harbor v2.4.0 的 arm 架构离线安装包,面向需要在 ARM 服务器或国产化平台上私有化部署容器镜像仓库的运维与开发人员。相比在线安装,离线包可规避网络受限环境下的镜像拉取难题,适合内网、信创及边缘计算等场景快速落地。压缩包共 6 个文件,约 402.34MB,包含 sh 安装脚本、gz 镜像归档、yml 配置文件及 license 等,覆盖部署所需的脚本、配置与镜像数据,解压后执行 install.sh 即可一键完成安装,前置依赖为 docker 与 docker-compose。目前已有 1576 人学习下载,说明该版本在 ARM 环境部署中具备一定参考价值。借助该资源,读者可省去逐一下载组件与手动配置的繁琐过程,直接获得可复用的离线部署方案,并对照配置文件理解 Harbor 各组件的参数组织方式,为后续版本升级与故障排查提供基础。

1. 从一台 ARM 服务器的离线部署说起:harbor 2.4.0 到底能解决什么

手里有一台 ARM 架构的服务器,网络隔离,不能连外网,但团队需要一个私有镜像仓库来管理容器镜像。这时候 Docker Hub 用不了,公有云仓库又不放心,harbor 就成了最现实的选择。harbor 2.4.0 这个版本在 ARM 平台上已经能跑,但离线安装的坑比 x86 多不少——镜像包要自己凑齐、docker-compose 的 ARM 兼容性要确认、离线包的目录结构跟在线安装完全不是一回事。这篇笔记面向的是手里有 ARM 服务器、需要在内网搭私有仓库的运维或后端,从离线包准备到 harbor 服务拉起,再到日常运维的坑,一步步拆开讲。如果你之前只在 x86 上装过 harbor,ARM 这套流程值得重新走一遍。

2. 离线包准备与 ARM 架构适配:从下载到目录结构

2.1 为什么 harbor 2.4.0 的离线包在 ARM 上要单独处理

harbor 官方发布的离线安装包默认是 x86_64 架构,ARM 平台不能直接用。harbor 2.4.0 的离线包本质上是一个压缩包,里面包含 harbor 各组件的 Docker 镜像 tar 包、docker-compose 模板、配置文件模板和安装脚本。在 x86 上,你下载harbor-offline-installer-v2.4.0.tgz解压就能用,但 ARM 上这个包里的镜像全是 amd64 的,docker load之后启动会直接报exec format error。

常见做法是两条路:一是找社区构建好的 ARM 版离线包,二是自己从源码构建 ARM 镜像再打包。我一般会先确认服务器 CPU 架构,再决定用哪种方式。uname -m返回aarch64就是 ARM64,返回x86_64就是 amd64。这个判断不做,后面全是白费功夫。

# 确认服务器架构 uname -m # 输出 aarch64 表示 ARM64 架构 # 确认 Docker 和 docker-compose 版本 docker --version docker-compose --version # harbor 2.4.0 要求 docker 17.06+ 和 docker-compose 1.18.0+

逻辑说明:uname -m是最直接的架构判断命令,ARM64 服务器通常返回aarch64。docker 和 docker-compose 的版本检查不能省,harbor 2.4.0 对 docker-compose 的版本有硬性要求,低于 1.18.0 会在prepare阶段直接报错退出。

参数说明:docker-compose 在 ARM 上建议用 1.29.x 版本,2.x 版本虽然也能用,但 harbor 2.4.0 的模板文件是按 1.x 语法写的,混用可能出现version字段不识别的问题。

2.2 离线包目录结构与关键文件说明

假设你已经拿到了 ARM 版的 harbor 离线包,解压后目录结构大致如下:

harbor/ ├── harbor.v2.4.0.tar.gz # 各组件镜像的 tar 包集合 ├── harbor.yml.tmpl # 配置文件模板 ├── install.sh # 安装脚本 ├── prepare # 环境准备脚本 ├── docker-compose.yml # 容器编排模板 ├── common.sh # 公共函数脚本 └── LICENSE

这里最关键的是harbor.v2.4.0.tar.gz,它里面包含了 harbor-core、harbor-portal、harbor-jobservice、registry、registryctl、postgresql、redis、nginx 等组件的镜像。ARM 版和 x86 版的区别就在这个 tar 包里——镜像的架构不同。

# 解压离线包 tar -xzvf harbor-offline-installer-v2.4.0-arm64.tgz # 进入解压目录 cd harbor # 查看镜像 tar 包大小,确认是否完整 ls -lh harbor.v2.4.0.tar.gz # ARM 版通常在 1.5GB 左右,明显偏小说明包不完整

逻辑说明:解压后先看 tar 包大小,ARM 版 harbor 的镜像包通常在 1.5GB 上下。如果只有几百 MB,大概率是下载不完整或者拿错了包。这一步花几秒钟,能省掉后面反复排查的时间。

参数说明:tar -xzvf中的z表示 gzip 解压,x是解压,v显示过程,f指定文件名。如果包是.tar而非.tgz,去掉z参数即可。

2.3 导入镜像与配置文件修改

镜像导入是离线安装的核心步骤。harbor 的install.sh脚本会自动执行docker load,但前提是harbor.v2.4.0.tar.gz在正确的位置。如果你手动导入,可以这样做:

# 手动导入所有镜像 docker load -i harbor.v2.4.0.tar.gz # 导入完成后查看镜像列表 docker images | grep goharbor # 应该能看到 harbor-core、harbor-portal、harbor-jobservice 等

逻辑说明:docker load会把 tar 包里的所有镜像层导入本地 Docker 存储。导入完成后用docker images过滤goharbor前缀,确认各组件镜像都在。如果某个组件缺失,启动时对应的容器会一直重启。

参数说明:-i指定输入文件。如果 tar 包是 gzip 压缩的,docker load 会自动识别,不需要额外解压。

配置文件harbor.yml是从harbor.yml.tmpl复制来的,需要改几个关键项:

# harbor.yml 关键配置 hostname: 192.168.1.100 # 改成服务器实际 IP 或域名 http: port: 80 # HTTP 端口,按需修改 https: # 如果不用 HTTPS,整段注释掉 port: 443 certificate: /path/to/cert.pem private_key: /path/to/key.pem harbor_admin_password: Harbor12345 # 管理员初始密码,建议改掉 database: password: root123 # 数据库密码,建议改掉 data_volume: /data # 数据存储目录,确保磁盘空间充足

逻辑说明:hostname必须改成实际可访问的 IP 或域名,否则客户端docker login会失败。data_volume是镜像和数据库的存储位置,默认/data,如果根分区空间不够,改成独立数据盘挂载点。

参数说明:harbor_admin_password是 admin 用户的初始密码,首次登录后建议在界面修改。database.password是内部 PostgreSQL 的密码,改掉能减少被扫描的风险。

3. 执行安装与验证:从 prepare 到 docker login

3.1 运行安装脚本与常见报错处理

配置改完后,执行安装脚本:

# 执行安装 ./install.sh # 如果只想安装核心组件,不带 Notary 和 Clair ./install.sh --without-notary --without-clair

逻辑说明:install.sh会依次执行prepare(生成最终 docker-compose.yml)、docker load(导入镜像)、docker-compose up -d(启动容器)。--without-notary和--without-clair用于跳过可选组件,ARM 平台上 Notary 的兼容性一般,建议先不装。

参数说明:--with-notary和--with-clair是显式启用,默认不启用。如果后续需要漏洞扫描,可以再单独装 Clair。

安装过程中最常见的报错是端口占用和镜像架构不匹配:

# 检查端口占用 netstat -tlnp | grep -E '80|443|5432|6379' # 如果 80 被 nginx 占用,改 harbor.yml 的 http.port # 然后重新执行 ./install.sh

逻辑说明:harbor 默认用 80 和 443,如果服务器上已有 nginx 或其他 Web 服务,会冲突。netstat检查后改端口是最快的解决方式。ARM 上如果报exec format error,说明镜像架构不对,需要重新获取 ARM 版镜像包。

参数说明:netstat -tlnp中t是 TCP,l是监听状态,n是数字显示端口,p显示进程。需要 root 权限才能看到进程名。

3.2 验证 harbor 服务状态与 docker login

安装完成后,用 docker-compose 查看容器状态:

# 查看容器运行状态 docker-compose ps # 正常情况应该看到 9 个左右的容器,状态都是 Up # 如果有 Exit 或 Restarting,查看对应日志 docker-compose logs harbor-core

逻辑说明:docker-compose ps列出所有容器的状态。harbor 2.4.0 正常运行时,harbor-core、harbor-portal、harbor-jobservice、registry、registryctl、postgresql、redis、nginx 这些容器都应该是 Up 状态。如果有容器反复重启,用docker-compose logs看具体报错。

参数说明:docker-compose logs后面跟服务名,不加服务名则输出所有日志。-f参数可以实时跟踪日志输出。

服务起来后,在另一台机器上测试登录:

# 在客户端机器上登录 harbor docker login 192.168.1.100 -u admin -p Harbor12345 # 如果 harbor 配了 HTTPS 但证书是自签的,需要加信任 # 或者直接在 docker daemon 配置里加 insecure-registries

逻辑说明:docker login验证 harbor 的认证服务是否正常。如果返回Error response from daemon: Get https://...: x509: certificate signed by unknown authority,说明证书不被信任。测试环境可以在/etc/docker/daemon.json里加insecure-registries。

参数说明:-u和-p分别是用户名和密码。生产环境建议用--password-stdin从标准输入读取密码,避免密码出现在命令历史里。

3.3 推送和拉取镜像的完整流程

登录成功后,测试镜像推送:

# 给本地镜像打 tag docker tag nginx:latest 192.168.1.100/library/nginx:latest # 推送镜像 docker push 192.168.1.100/library/nginx:latest # 拉取镜像 docker pull 192.168.1.100/library/nginx:latest

逻辑说明:harbor 的镜像路径格式是hostname/project/image:tag。library是默认项目,也可以先在 harbor 界面创建新项目再推送。推送成功后,在 harbor 的 Web 界面能看到镜像列表和大小。

参数说明:docker tag只是给镜像加一个别名,不产生新镜像。推送时 harbor 会校验认证信息,如果项目不存在或权限不足会返回denied。

4. 避坑与常见问题:ARM 离线安装的五个血泪教训

4.1 镜像架构不匹配导致容器反复重启

现象:docker-compose ps显示 harbor-core 状态为Restarting,日志里报exec format error。

原因:离线包里的镜像还是 amd64 架构,ARM 服务器无法执行。

解决:确认离线包是 ARM64 版本,或者用docker inspect查看镜像架构:

docker inspect goharbor/harbor-core:v2.4.0 | grep Architecture # 输出 "Architecture": "arm64" 才是正确的

4.2 docker-compose 版本过高导致语法不兼容

现象:./install.sh执行到prepare阶段报Unsupported config option for services或version is unsupported。

原因:docker-compose 2.x 版本对version字段的处理和 1.x 不同,harbor 2.4.0 的模板是按 1.x 写的。

解决:降级到 docker-compose 1.29.x,或者手动修改docker-compose.yml去掉version: '2'这一行。

4.3 数据目录磁盘空间不足导致安装中断

现象:安装过程中报no space left on device,postgresql 容器启动失败。

原因:data_volume默认指向/data,如果根分区空间不够,镜像和数据库写入会失败。

解决:安装前用df -h /data确认空间,建议至少预留 50GB。如果不够,在harbor.yml里把data_volume改到大容量挂载点。

4.4 端口冲突导致 nginx 容器无法启动

现象:docker-compose ps显示 nginx 状态为Exit,日志报bind: address already in use。

原因:服务器上已有服务占用了 80 或 443 端口。

解决:netstat -tlnp | grep 80找到占用进程,要么停掉冲突服务,要么在harbor.yml里改http.port为其他端口。

4.5 离线环境下时间不同步导致证书校验失败

现象:docker login报x509: certificate has expired or is not yet valid。

原因:内网服务器时间偏差过大,HTTPS 证书校验不通过。

解决:安装前用date检查时间,偏差超过几分钟就手动校准或配置内网 NTP 源。这个坑很隐蔽,日志里不会直接说时间问题,只会报证书错误。

5. 进阶技巧:ARM 离线环境的日常运维与镜像清理

harbor 跑起来只是第一步,日常运维里最头疼的是镜像清理和存储管理。harbor 2.4.0 自带的垃圾回收功能在 ARM 上同样可用,但触发方式和 x86 略有不同。我一般会先配好保留策略,再手动触发 GC,避免存储被旧镜像撑满。

保留策略在 harbor 界面的「项目」→「策略」里配置,可以按镜像标签数量或保留天数来清理。比如设置「保留最近 10 个标签」,超过的自动删除。这个策略对 ARM 环境尤其重要,因为 ARM 镜像的层复用率不如 x86,同样的镜像数量占用的存储可能更多。

手动触发垃圾回收:

# 停止 harbor(GC 需要停服务) docker-compose stop # 执行 GC docker run -it --name gc --rm --volumes-from registry \ goharbor/registry-photon:v2.4.0 garbage-collect \ /etc/registry/config.yml # 重新启动 harbor docker-compose start

逻辑说明:harbor 的 GC 需要 registry 容器停止写入,所以要先docker-compose stop。--volumes-from registry让 GC 容器挂载 registry 的数据卷,garbage-collect是 registry 自带的命令,/etc/registry/config.yml是配置文件路径。

参数说明:--rm表示容器退出后自动删除,避免残留。GC 完成后用docker-compose start恢复服务。整个过程通常几分钟到十几分钟,取决于镜像数量。

另一个实用技巧是定期备份数据库和配置文件:

# 备份 PostgreSQL 数据库 docker exec harbor-db pg_dump -U postgres registry > backup_$(date +%Y%m%d).sql # 备份 harbor.yml 和 docker-compose.yml cp harbor.yml /backup/harbor.yml.$(date +%Y%m%d) cp docker-compose.yml /backup/docker-compose.yml.$(date +%Y%m%d)

逻辑说明:harbor 的元数据存在 PostgreSQL 里,镜像层存在文件系统里。数据库备份能恢复项目、用户、策略等信息,配置文件备份能快速重建环境。这两个备份加起来,基本能覆盖大部分故障场景。

参数说明:pg_dump -U postgres registry导出 registry 数据库,$(date +%Y%m%d)生成日期后缀,方便区分版本。

从那以后我每次在 ARM 上部署 harbor,都会先跑一遍uname -m和docker inspect确认架构,再检查磁盘和端口,最后才执行安装脚本。这套流程走下来,基本没再翻过车。希望帮到你。

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进