ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ARM64服务器离线部署Harbor v2.13.1:从镜像架构到安装配置避坑指南

ARM64服务器离线部署Harbor v2.13.1:从镜像架构到安装配置避坑指南 简介一份专为ARM64架构下Kubernetes与Docker环境打造的离线部署包内置Harbor最新v2.13.1版本并以tgz格式封装方便直接传递与部署。压缩包内共含6个文件核心镜像压缩包harbor.v2.13.1.tar.gz承载仓库服务镜像install.sh与common.sh负责安装流程与公共函数harbor.yml.tmpl是配置模板另有prepare准备文件及许可证文件整体大小约679MB。这种打包方式免去在线拉取镜像的不确定性特别适用于内网隔离或网络受限的生产环境运维工程师依此即可快速搭建企业级镜像仓库并根据业务需求灵活调整存储后端、TLS证书与认证策略。截至目前已有528人学习下载说明离线交付方案在真实场景中已获得充分验证。一次获取即拥有完整物料有助于显著缩短Harbor部署周期降低因网络故障导致的交付风险。1. ARM64 服务器上部署 Harbor v2.13.1离线安装包为什么不能直接用Harbor v2.13.1 的 ARM64 离线安装包听起来就是把官方离线包下载下来解压再install.sh的事实际动手的人会发现这条路经常走不通。官方离线安装包里的镜像包默认按 amd64 架构打进去ARM64 服务器上执行安装脚本镜像能 load 进去容器一运行就报exec format error服务根本起不来。这篇文章先把离线安装包的构成拆开讲清楚再给一条在 ARM64 环境下手动拉镜像、替换镜像包、跑通install.sh的完整路径顺手把推送失败、架构不匹配这类高频坑一起排掉。适合正在搭内网镜像仓库的运维和交付工程师尤其适合手里只有一台 ARM64 服务器、机器还不能联网的场景。2. 在 ARM64 机器上把镜像拉全先解决镜像清单和架构核对问题搞 ARM64 离线包的第一步不是急着下离线包而是先搞清楚离线安装包里的镜像包到底装了什么、是什么架构。官方发布的harbor-offline-installer-v2.13.1.tgz核心是里面那一个harbor.v2.13.1.tar.gz。install.sh做的事很直接docker load导入这个 tar 里的镜像再用prepare渲染出docker-compose.yml最后docker compose up -d把服务拉起来。所以这个 tar 里的镜像架构决定了整套 Harbor 能不能在目标机器上起来。2.1 官方离线包和 ARM64 的错位出在哪个环节先看离线安装包解压出来的结构确认每个文件的作用文件作用ARM64 离线安装要不要动harbor.v2.13.1.tar.gzHarbor 全部容器的镜像包gzip 压缩需要替换成 ARM64 架构的镜像包docker-compose.ymlcompose 模板install.sh用prepare渲染一般不手改用prepare生成最终版install.sh一键安装入口负责 load 镜像和启动服务不用改脚本本身harbor.yml.tmpl配置模板复制为harbor.yml后修改prepare配置生成二进制不用动但它决定 compose 里的镜像名官方离线包在打包时镜像包默认按构建机所在的 amd64 架构导出了一份harbor.v2.13.1.tar.gz。你把它搬到 ARM64 机器上docker loadDocker 不会拦镜像名、tag 都对但容器真正执行二进制时CPU 不认识 amd64 指令集于是容器反复重启或直接退出。这就是很多人第一步踩的坑包能装但跑不起来。那能不能把官方包里的 tar 解出来重新打成 arm64也可以但没必要。社区里更常规的做法是自己在可联网的 ARM64 机器上把所有镜像拉一遍、导出、再替换回离线包。这个过程最怕的就是镜像清单背错Harbor 各个小版本改过几次镜像名比如 registry 相关镜像从goharbor/registry-photon改成了goharbor/harbor-registry。背死名单不如每次从 compose 模板里现提。2.2 在 ARM64 机器上批量拉取镜像并导出镜像清单与 docker pull 脚本准备一台能联网、并且架构确实是 arm64 的机器在上面执行下面的脚本。这一步的关键是让 Docker 根据当前机器的架构去拉对应的镜像层。#!/bin/bash # 在可联网、架构为 arm64 的机器上执行 # 拉取 Harbor v2.13.1 全部服务镜像并导出成一个 tar set -euo pipefail HARBOR_VERSIONv2.13.1 IMAGES( goharbor/prepare:${HARBOR_VERSION} goharbor/harbor-log:${HARBOR_VERSION} goharbor/harbor-registry:${HARBOR_VERSION} goharbor/harbor-registryctl:${HARBOR_VERSION} goharbor/harbor-db:${HARBOR_VERSION} goharbor/redis-photon:${HARBOR_VERSION} goharbor/harbor-core:${HARBOR_VERSION} goharbor/harbor-portal:${HARBOR_VERSION} goharbor/harbor-jobservice:${HARBOR_VERSION} goharbor/nginx-photon:${HARBOR_VERSION} goharbor/harbor-exporter:${HARBOR_VERSION} ) for img in ${IMAGES[]}; do echo pulling ${img} docker pull ${img} done docker save ${IMAGES[]} -o harbor-arm64-images.tar gzip -9 harbor-arm64-images.tar mv harbor-arm64-images.tar.gz harbor.v2.13.1-arm64.tar.gz ls -lh harbor.v2.13.1-arm64.tar.gz脚本逻辑不复杂但有几个地方要注意。镜像数组里特意放了prepare和harbor-log这两个是install.sh和 compose 启动时都会用到的辅助镜像漏掉它们安装脚本执行到生成配置那一步就会报找不到镜像。HARBOR_VERSION单独设成变量以后升级到下一个版本只改这一处就能复用脚本。docker save一次性把数组里所有镜像导出成一个 tar比逐个 save 再合并省事得多。导出的 tar 用的是原始镜像名和 tag比如goharbor/harbor-core:v2.13.1到目标机器上docker load之后compose 里引用的镜像名能直接对上不需要再 tag。gzip 压缩是必须的因为替换回离线包时install.sh认的是.tar.gz后缀。如果你拿到的官方离线包里已经有了一份现成的镜像清单也可以先解包再从docker-compose.yml里抓image:字段核对一遍cd harbor grep -E image: docker-compose.yml | sed -E s/.*image:\s*?([^])?/\1/ | sort -u把这份清单和上面脚本里的数组对一下缺谁补谁。以 compose 模板实际引用为准别只信网上的旧教程。2.3 架构核对docker image inspect 和 manifest 两种查法拉完镜像不要急着传走先就地核对一次架构这一步能省掉后面一整轮排错。最直接的命令docker image inspect goharbor/harbor-core:v2.13.1 --format {{.Os}}/{{.Architecture}}在 arm64 机器上执行正常输出应该是linux/arm64。如果输出linux/amd64说明这台机器本身架构不对或者 Docker 服务的平台参数被改过拉下来的镜像仍然是 x86 的。还有一种情况镜像仓库本身是多架构的Docker 会根据当前系统的uname自动选择对应的 manifest。想确认镜像仓库支持哪些架构用docker manifest inspectdocker manifest inspect goharbor/harbor-core:v2.13.1返回的manifests列表里会列出amd64、arm64等平台的 digest。这里有个容易误解的点manifest 里有 arm64不代表你本地拉下来的镜像就是 arm64。Docker 在你 pull 的时候才解析平台所以还是要以docker image inspect本机实际镜像的结果为准。如果你在当前机器上看到的是 amd64后面传到 ARM64 真机上执行时就会碰到exec format error。这个错在 x86 机器上跑 arm64 镜像时也会出现严重情况下内核会直接报类似bad linux arm64 image magic!的信息那说明镜像文件头与 CPU 架构完全不匹配。看到这类问题先别急着排查 Harbor 配置先回头查架构。3. 组装离线安装包替换镜像包让 install.sh 在 ARM64 上跑通镜像拉好、架构也验证过接下来就是把自制的 ARM64 镜像包装回官方离线安装包里。这个环节做法很多有人直接到目标机器上手动docker load也有人把整个离线包重新打包一份。这里我推荐替换官方包里的harbor.v2.13.1.tar.gz因为install.sh的执行流程是死板的它一定会 load 包内自带的那份镜像包手动提前 load 也会被它再次覆盖所以直接从源头替换才最干净。3.1 两种装配思路为什么选替换 tar 而不是手动 load一种常见做法是目标机器先手动docker load自制的 ARM64 镜像然后再执行官方install.sh。听着合理但install.sh内部会自带执行一次docker load -i ./harbor.v2.13.1.tar.gz。如果包里的镜像还是 amd64这次 load 会把你手动加载的 arm64 镜像按同名 tag 覆盖掉等于白做。第二种做法是替换 tar 包。把第 2 章导出的harbor.v2.13.1-arm64.tar.gz改名成harbor.v2.13.1.tar.gz替换掉官方离线包里的原文件。之后install.shload 到的就是 arm64 镜像compose 启动时镜像名和 tag 也完全对得上。这个方案还能保留官方安装脚本的原始流程后续升级维护也贴近官方操作习惯。3.2 替换命令与第一次执行 install.sh 的完整流程把自制镜像包和官方离线包都上传到目标 ARM64 服务器后按下面步骤操作# 进入工作目录解压官方离线安装包 tar -xzf harbor-offline-installer-v2.13.1.tgz cd harbor # 原包改名留底别删出问题还能找回 amd64 原版 mv harbor.v2.13.1.tar.gz harbor.v2.13.1.tar.gz.x86_backup # 自制 ARM64 镜像包复制进目录并替换成官方脚本期望的文件名 cp /data/harbor.v2.13.1-arm64.tar.gz ./harbor.v2.13.1.tar.gz # 生成配置 cp harbor.yml.tmpl harbor.yml vim harbor.yml # 一键安装脚本会自动 load 当前目录的镜像包 sudo ./install.sh参数上说明几个点/data是镜像包临时存放的路径按自己习惯改替换后的harbor.v2.13.1.tar.gz必须保持这个文件名install.sh脚本里写死的就是这个名字留底的原包名改成.x86_backup后缀是为了避免和新的.tar.gz冲突。执行install.sh时注意屏幕输出的Loaded image:行。正常情况下应该能看到goharbor/harbor-core:v2.13.1等一长串镜像逐个加载。如果这一阶段出现exec format error说明这个自制包本身就不是 arm64回去做第 2 章的核对。如果加载顺利但后面docker compose up起容器时报某个镜像 missing大概率是镜像数组漏了回可联网机器补拉对应镜像再重新导出。3.3 目标机器没有 Docker 时怎么离线装 Docker 环境有的 ARM64 目标服务器是真正的裸机连 Docker 都没有。这时先把 Docker 引擎装上再谈 Harbor。如果你的内网源里有 Docker 的 apt 源那直接 apt 安装即可完全没有内网源时我一般会在可联网的同架构机器上把 docker 相关 deb 包用apt download抓下来或者直接拷贝 docker 二进制和 containerd 静态包过去。# 在可联网的 Ubuntu ARM64 机器上 mkdir docker-debs cd docker-debs apt-get download docker-ce docker-ce-cli containerd.io docker-compose-plugin # 打包传输到内网机器 tar -czf docker-debs-arm64.tar.gz ./docker-debs到目标机器解压后执行tar -xzf docker-debs-arm64.tar.gz cd docker-debs sudo dpkg -i ./*.deb || sudo apt-get -f install -y要注意版本Harbor 2.x 对 Docker 版本有硬性要求Docker 版本太低compose 的某些配置项不识别装起来会莫名报错。装完后用docker version看一眼Server 和 Client 版本都别太老。4. harbor.yml 配置与部署端口、密码、数据目录三个必调参数镜像和安装脚本都准备好了最后成不成一半看harbor.yml配得对不对。Harbor 的配置集中在harbor.yml模板里有大量注释和默认项真正部署时只需要抓住三个必调参数hostname、HTTP/HTTPS 端口、data_volume。其他项保持默认也能跑但这三个参数定得不合理后面改起来非常痛苦。4.1 hostname、端口和 data_volume 怎么设hostname是 Harbor 对外提供服务的地址这个值不仅是页面访问地址还会写进镜像 tag 里。你 push 一个镜像时的完整地址例如192.168.209.133:8080/library/nginx:v1这前面的主机名就必须和hostname参数一致否则 push 出去的项目路径都是错的。内网部署直接把hostname写成服务器 IP 最省事不要写localhost或127.0.0.1那样外网机器没法访问docker 客户端登录时还会因为地址不匹配出现奇怪的连接问题。端口方面Harbor 默认走 80 和 443。如果 80 端口被占用或者你想让页面用8080起改http.port就行。这里有一个常见误区改了http.port之后访问地址变成http://ip:8080docker login 和 docker tag 的地址也要跟着带端口一个地方漏改后面 push 就找不到仓库。HTTPS 部分如果暂时没有证书直接把注释解开并填证书路径就行但多数内网离线环境第一轮都是先跑 HTTP后者更简单也更不容易踩证书坑。data_volume是数据落盘目录Harbor 的数据库、镜像存储、证书密钥全部存在这个目录下面。默认值是/data/harbor建议改到一个空间大、最好单独挂载的路径例如/opt/harbor/data。这个参数最坑的地方在于一旦容器跑起来生成了数据再改路径不会自动迁移等于把已有数据丢在一边。所以第一次部署就要定好。4.2 最小可用配置先跑 HTTP把 HTTPS 留到以后下面是一份内网 ARM64 环境最小可用的harbor.yml# Harbor v2.13.1 最小配置适用于内网离线部署 hostname: 192.168.209.133 http: port: 8080 # 暂时注释掉 https避免因为证书问题导致起不来 # https: # port: 443 # certificate: /data/harbor/certs/server.crt # private_key: /data/harbor/certs/server.key # 初始管理员密码要求至少 8 位且包含大小写和数字 harbor_admin_password: Harbor12345 # 数据目录务必提前规划后续迁移很麻烦 data_volume: /opt/harbor/data配置里的harbor_admin_password是初始密码首次登录admin时用的就是它。模板里默认值是Harbor12345上线前一定改掉。database相关参数如果是单机部署、使用内置 PostgreSQL可以不动只有外部数据库时才需要显式配置database段的连接信息。这里要特别说一句https段如果当前不用直接注释掉而不是留空路径。之前见过有人把证书路径填成一个不存在的文件结果./install.sh执行到生成配置时因为找不到证书文件直接退出。Harbor 对配置的校验比想象中严格宁可先全注释、跑通再加密。4.3 部署后验证容器清单、接口探活和 docker login 一条线./install.sh跑完后用下面的命令验证服务状态# 查看 Harbor 相关容器是否全部进入 Up 状态 docker ps --format table {{.Names}}\t{{.Status}}\t{{.Image}} | grep -E harbor|nginx|registry|core|jobservice|portal|redis|db|exporter # 接口探活返回字符串 pong 即正常 curl -s http://192.168.209.133:8080/api/v2.0/ping # 用 docker 客户端做一次真实登录 docker login 192.168.209.133:8080 -u admin -p Harbor12345探活时如果curl返回一串 HTML 或跳转页面别急着下结论先用curl -s -o /dev/null -w %{http_code}看 HTTP 状态码。Harbor 的 API 路径/api/v2.0/ping在 2.x 里是健康检查接口返回pong才代表核心服务正常。页面能打开但 ping 不通多半是 core 服务没起来要去docker logs里找原因。docker ps输出里容器名以harbor-开头比如harbor-core、harbor-portal、harbor-registry。正常时全部是Up状态如果出现循环重启立刻看日志尤其关注是不是因为架构不对导致exec format error。5. ARM64 离线部署避坑架构报错、推送失败与升级前后的排查记录这一章把我在 ARM64 离线部署 Harbor 过程中踩过的、以及在群里看别人踩过的五个高频问题列出来。每个问题都按现象、原因、解决三步走大部分问题和 Harbor 本身没关系全是环境或使用习惯造成的。5.1 容器反复重启日志只给一句 exec format error现象docker ps看到 harbor-core 或 harbor-registry 状态是 Restartingdocker logs harbor-core只显示一行exec /usr/bin/core: exec format error。原因镜像包里的二进制是 amd64 架构放到 ARM64 主机上跑不起来。最常见于直接把官方离线包拿去装或者手动 load 时 load 错了包。解决先在安装机上执行docker image inspect goharbor/harbor-core:v2.13.1 --format {{.Architecture}}确认输出是arm64。如果架构不对按第 2 章重新拉取按第 3 章替换harbor.v2.13.1.tar.gz然后sudo ./install.sh重新安装。5.2 harbor 推送失败登录时 get https://192.168.209.133/v2/ dial tcp 连接被拒现象docker login 192.168.209.133:8080或docker push时报下面这类错误Error response from daemon: Get https://192.168.209.133/v2/: dial tcp 192.168.209.133: ... connect: connection refused原因分三种第一种Harbor 容器没起来尤其是 nginx 或 core 挂了第二种harbor.yml里http.port改成了别的端口但 docker login 命令还是用默认 80流量被拒第三种目标机器和 Harbor 之间有防火墙端口没放通。解决先curl -s http://192.168.209.133:8080/api/v2.0/ping看服务通不通通的话检查 docker 客户端地址是否带端口不带端口默认走 443和配置不一致就会出现 dial tcp 连不上。确认端口没问题后再检查宿主机防火墙ufw status或firewall-cmd --list-all看有没有放行对应端口。这个错最常见的原因不是配置而是端口没带对登录和推送地址必须与hostname:port完全一致。5.3 在 x86 上用 qemu 模拟 arm64 拉镜像真机上根本不能用现象你在 x86 笔记本上装了个 qemu 模拟的 arm64 虚拟机在里面用 docker 拉了一堆 goharbor 镜像导出后传到真机 ARM64 服务器却仍报架构错误有的场景直接报bad linux arm64 image magic!。原因qemu 用户态模拟并不能改变 Docker 宿主机解析镜像的方式。镜像层到底是 arm64 还是 amd64取决于镜像构建时的架构和 Docker Engine 解析 manifest 的平台而不是 qemu 模拟出来的uname。在 x86 机器上做出来的东西拿到真机上跑往往还是 amd64。解决不要在 x86 上用 qemu 模拟出来的环境做这个事。老老实实找一台真实的 ARM64 机器哪怕是云厂商的 ARM64 实例在上面执行docker pull和docker save。这个环节省不得我也在这里翻过车抱着侥幸心理省一台机器结果浪费了整个下午排错。5.4 docker login 被证书拦截连私服都连不上现象Harbor 服务正常登录时却报x509: certificate signed by unknown authority或者提示证书 CN 不匹配。还有一种是http: server gave HTTP response to HTTPS client。原因Harbor 配置开了 HTTPS但用的是自签证书docker 客户端不信任这本证书或者 Harbor 配了 HTTP而 docker 客户端默认对非 localhost 仓库走 HTTPS。解决两种选一个。第一种继续用 HTTPS把 Harbor 的 CA 证书加到每台 docker 客户端的/etc/docker/certs.d/目录里。第二种内网环境图省事直接让 docker 跳过安全校验编辑/etc/docker/daemon.json。{ insecure-registries: [192.168.209.133:8080] }改完重启 dockersudo systemctl restart docker这里提醒一下修改daemon.json会重启 Docker本机所有容器都会短暂中断不要在业务高峰期操作。而且insecure-registries里的地址要带端口和登录地址保持一致。5.5 升级前没有备份数据库 schema 迁移失败后什么都找不回来现象从低版本升级到 v2.13.1upgrade.sh执行到数据库迁移阶段报错Harbor 起不来。有人想直接回退镜像版本但数据库已经做过迁移低版本连不上高版本的库整个数据目录变成半死不活的状态。原因Harbor 的版本升级不只是镜像 tag 变了数据库结构也会变。迁完一旦失败没有停机备份就只能拿残留数据碰运气。解决升级前把data_volume整个目录打包备份再把 docker 卷也备一份。备份命令如下# 停服务避免备份过程中数据写入 cd harbor sudo docker compose down # 打包整个数据目录这一步是后悔药 sudo tar -czf harbor-data-backup-$(date %Y%m%d).tar.gz /opt/harbor/data备份完再解压新版离线包按第 3 章方法替换镜像把旧harbor.yml复制到新版目录执行sudo ./upgrade.sh。升级脚本会先检查当前版本再做数据库迁移。备份文件放机器上别删至少保留到确认业务正常一周。6. 升级到 v2.13.1 并做冒烟验证备份、救回、推送三连如果是已经跑着 Harbor v2.11 或 v2.12 的环境想升级到 v2.13.1不能直接把新镜像替换上去重启。Harbor 的版本升级有固定套路官方脚本叫upgrade.sh它会读取旧的版本信息然后按顺序迁移数据库结构。我一般这么走先停服备份再把新版离线包解压把旧harbor.yml复制过去最后执行sudo ./upgrade.sh。升级脚本跑完后容器会重建这个阶段不要急着进页面先等两分钟让数据库连接池起来。升级完之后的验证我习惯做一次 docker push 冒烟测试既能验证镜像服务也能把权限、网络、存储一次测到# 登录新版本 Harbor docker login 192.168.209.133:8080 -u admin -p Harbor12345 # 拉一个本地镜像打好 tagpush 到 Harbor 的 library 项目 docker pull busybox:latest docker tag busybox:latest 192.168.209.133:8080/library/busybox:smoke docker push 192.168.209.133:8080/library/busybox:smoke # 从 Harbor 拉下来验证完整闭环 docker rmi 192.168.209.133:8080/library/busybox:smoke docker pull 192.168.209.133:8080/library/busybox:smoke整个过程跑通说明升级后的核心链路没问题。别只看容器起来就宣布成功到这里为止最容易漏掉的是升级后数据库里旧的镜像仓库清单还在不在如果 push 后页面里能看到这个smoketag那升级确实没丢数据。最后说个习惯。我每次升级前都要做一次完整备份而且备份文件命名里带上日期。有一次图省事没做备份数据库在迁移中途报错最后只能从残留数据里手工捞项目配置折腾到凌晨。自此之后凡是涉及 Harbor 这类带数据库状态的服务停服备份和升级后冒烟测试都变成固定动作。这套流程不复杂但能给你兜住绝大多数意外希望帮到你。本文还有配套的精品资源点击获取
返回列表