
簡介面向ARM64架構的Harbor離線部署包版本為當前最新的v2.13.1專供在鯤鵬、飛騰等ARM處理器服務器上搭建鏡像倉庫使用尤其適合Kubernetes與Docker離線環(huán)境下的運維場景。壓縮包以tgz格式封裝共6個文件包含2個shell腳本負責安裝與配置處理、1個鏡像tar.gz文件內含Harbor本體鏡像以及l(fā)icense、prepare工具和配置模板整體大小679.05MB。資源下載后可直接執(zhí)行安裝腳本完成部署無需在線拉取大量容器鏡像適合內網(wǎng)隔離或網(wǎng)絡受限的機房環(huán)境通過附帶的prepare和yml模板可靈活調整存儲、TLS及認證參數(shù)。該資源已持續(xù)更新至v2.13.1瀏覽學習人數(shù)已有526人對于需要在ARM64平臺上快速上線Harbor的運維或開發(fā)人員來說是一份省時省力的工具包。1. 拿到 ARM64 服務器Harbor v2.13.1 離線安裝包先別急著裝拿到一臺飛騰或鯤鵬的 ARM64 服務器系統(tǒng)是麒麟 V10 或 CentOS 7下一步要在內網(wǎng)部署 Harbor v2.13.1。別急著從網(wǎng)上隨便找一個“ARM64 版離線安裝包”就裝我在這里翻過不只一次車下載的 tgz 解壓后docker load 時提示 manifest 不匹配或者鏡像加載成功容器一啟動就報 exec format error。Harbor 的離線安裝包不是源碼包它本質上是“預打包的 Docker 鏡像 安裝腳本”鏡像架構決定這個包能不能在當前主機直接跑。這篇筆記從離線包的拆解、ARM64 離線包的自制、內網(wǎng) install.sh 完整落地到常見排錯按一條可復現(xiàn)的流程講完。適合負責內網(wǎng)鏡像倉庫交付、幫機房做離線部署的人照著走能直接復現(xiàn)。2. 拆解 Harbor v2.13.1 離線包鏡像架構、文件組成和識別方法安裝包文件名按版本號來常見的是harbor-offline-installer-v2.13.1.tgz單看文件名很難直接分辨 amd64 還是 arm64。真正決定架構的是包內那個鏡像壓縮包。先把離線包的組成和架構判斷方法說清楚后面做 ARM64 版才有依據(jù)。2.1 離線安裝包解開后核心其實是一個鏡像歸檔把官方離線包解壓進入harbor目錄關鍵文件是可預期的install.sh負責安裝prepare負責根據(jù)harbor.yml生成 compose 配置harbor.yml.tmpl是配置模板common.sh是腳本公共函數(shù)。這里最值得注意的文件是harbor.v2.13.1.tar.gz它是用docker save導出的全部 Harbor 鏡像歸檔。tar -xzf harbor-offline-installer-v2.13.1.tgz cd harbor ls -lh我通常先看這個列表再判斷離線包完成度。一個合格的離線包不需要網(wǎng)絡install.sh會先把harbor.v2.13.1.tar.gz用docker load加載進本地再由docker compose up啟動。所以只要這個鏡像歸檔的架構和當前主機不匹配后面全部白搭??匆粋€離線包是不是能直接用第一件事不是改配置而是查鏡像歸檔里的架構字段。docker save出來的 tar 內部有manifest.json和每層鏡像的 config 文件config 文件里的architecture字段會明確寫amd64還是arm64。文件內部結構大概是manifest.json、若干layer.tar或blobs/sha256/...、還有一份記錄鏡像和 tag 對應關系的repositories。這些信息在安裝失敗時是排查的第一線索。2.2 ARM64 和 x64 的鏡像差異為什么繞不過去ARM64 和 x64 的差異不是改個文件名就能解決的。Harbor 的容器鏡像里harbor-core、harbor-jobservice是 Go 編譯的二進制harbor-portal是 Nginx 加靜態(tài)文件harbor-db是 PostgreSQL基礎鏡像各自對應官方平臺版本。x86 指令集編譯出來的二進制在 ARM64 內核上無法執(zhí)行反過來也一樣。就算docker load把鏡像加載成功容器起來時也會因為缺exec format error或exec user process caused: exec format error而退出。在 ARM64 v8a 上部署還有一個容易忽略的點ARM64 下存在 v8.0、v8.1、v8.2 等微架構差異大部分商用鏡像都按linux/arm64/v8或更低的兼容級別打包飛騰、鯤鵬這類處理器通常能兼容運行 v8.0 基礎鏡像。所以看到arm64/v8直接采用即可不必為某顆具體芯片型號單獨找安裝包。很多“偽 ARM64 離線包”的問題也出在這有的人只是把 amd64 的鏡像 tar 原樣改了個名或者在 x86 機器上沒有經(jīng)過docker buildx --platform linux/arm64構建就重新打了一個壓縮包。這種包在 ARM64 機器上要么加載報錯要么運行時報格式錯誤。判斷標準只有一個鏡像或鏡像歸檔里的實際 platform 字段而不是文件名帶了什么后綴。2.3 一分鐘內定位離線包架構的檢查手段在目標 ARM64 機器上原地驗證最直接。先docker load再對任意一個 Harbor 鏡像做inspect看看 Architecture 字段是不是 arm64。docker load -i harbor.v2.13.1.tar.gz docker image inspect goharbor/harbor-core:v2.13.1 --format {{.Os}}/{{.Architecture}}輸出如果出現(xiàn)linux/arm64說明鏡像歸檔確實是 ARM64 可用如果顯示linux/amd64這個離線包在當前 ARM64 機器上是起不來容器的。還有人習慣用docker run --rm goharbor/harbor-core:v2.13.1 true做冒煙測試如果直接報exec format error基本可以確認架構不匹配。這個方法在拿到任何第三方離線包時都適用不用等整個安裝流程跑完才后悔藥。3. 制作并安裝 Harbor v2.13.1 的 ARM64 版離線包從導出鏡像到 install.sh 跑通如果官方或第三方給的離線包架構不對最常見的做法不是等別人重新發(fā)布而是自己拿一臺能聯(lián)網(wǎng)的 ARM64 機器重新導出鏡像再替換到離線包里。這套流程我至少走了三遍把步驟固定下來能省很多時間。3.1 準備一臺能聯(lián)網(wǎng)的 ARM64 機器或者用 QEMU 模擬 arm64 環(huán)境先決條件是有 Docker 服務并且這臺機器能訪問 Harbor 鏡像倉庫的源站。常見做法是在臨時的一臺 ARM64 云主機或飛騰開發(fā)板上完成導出再把產(chǎn)物拷貝到內網(wǎng)。沒有 ARM64 實體機時用 QEMU 模擬 arm64 也成立宿主 x86 機器上裝qemu-user-static配合 Docker 的 binfmt 機制pull 時指定--platform linux/arm64/v8一樣能把 ARM64 鏡像拉到本地歸檔。我一般更推薦直接找一臺真實 ARM64 機器而不是長期依賴 QEMU。原因很簡單Harbor 安裝過程里容器涉及網(wǎng)絡、存儲、systemd 資源限制QEMU 下的運行表現(xiàn)和物理 ARM64 機器有差異特別是權限和 sysctl 相關的錯誤只有真機才能暴露。3.2 拉齊 Harbor 鏡像清單并導出 ARM64 鏡像歸檔Harbor v2.13.1 安裝涉及的鏡像包括 core、jobservice、portal、registry、registryctl、db、log、nginx、redis、trivy 等。先在一臺 ARM64 機器上配置好 Docker逐個 pull再統(tǒng)一用docker save導出一個歸檔文件。IMAGE_LISTgoharbor/harbor-core:v2.13.1 \ goharbor/harbor-jobservice:v2.13.1 \ goharbor/harbor-portal:v2.13.1 \ goharbor/harbor-registry:v2.13.1 \ goharbor/harbor-registryctl:v2.13.1 \ goharbor/harbor-db:v2.13.1 \ goharbor/harbor-log:v2.13.1 \ goharbor/nginx-photon:v2.13.1 \ goharbor/redis-photon:v2.13.1 docker pull goharbor/harbor-core:v2.13.1 docker image inspect goharbor/harbor-core:v2.13.1 --format {{.Architecture}}/{{.Os}} | grep arm64 docker save $IMAGE_LIST | gzip harbor.v2.13.1.arm64.tar.gz這段命令里docker pull會按當前機器的架構拉取ARM64 機器上拉到的就是 arm64 鏡像。docker image inspect用 Go 模板只輸出os/architecture用來確認拉出來的確實是 arm64。最后docker save把鏡像歸檔成單個 tar 流再 gzip 壓縮避免內網(wǎng)拷貝時占用太多空間。如果你的鏡像源不是默認倉庫需要提前做好 registry mirror 或直連源站的網(wǎng)絡配置否則在 ARM64 機器上拉鏡像也會卡在第一步。在這之后要把官方離線包里的原鏡像歸檔替換掉。官方離線包里的harbor.v2.13.1.tar.gz如果確認是 amd64 的先備份再把新導出的歸檔改成同名文件。cd harbor mv harbor.v2.13.1.tar.gz harbor.v2.13.1.tar.gz.amd64.bak cp ../harbor.v2.13.1.arm64.tar.gz ./harbor.v2.13.1.tar.gzinstall.sh調用時并不校驗內容是否來自官方只認文件名是否存在。替換完成后這個離線包就成了真正可用的 ARM64 版。需要提醒一點tar 文件體積通常不小建議在拷到內網(wǎng)前先算一次 sha256和目標機上的文件做比對避免傳輸中斷造成歸檔損壞。3.3 按內網(wǎng)場景修改 harbor.ymlhostname、存儲與端口離線替換做完接著改harbor.yml。官方包解壓后自帶harbor.yml.tmpl先復制成harbor.yml。核心配置項有三個hostname、http/https、data_volume。cp harbor.yml.tmpl harbor.yml典型的內網(wǎng)最小配置長這樣hostname: 192.168.10.20 http: port: 80 https: port: 443 certificate: /data/cert/harbor.crt private_key: /data/cert/harbor.key data_volume: /data/harbor log: level: info database: password: ChangeMe123參數(shù)說明hostname必須是客戶端能訪問到的地址不能寫 localhost否則其他機器docker login會失敗內網(wǎng)沒有 DNS 時直接用管理 IP 最省事。http.port建議保留 80Harbor 的prepare腳本會對 hostname 和端口生成對應的docker-compose.yml。https默認是打開的生產(chǎn)環(huán)境建議用自簽證書如果前期只想在隔離網(wǎng)絡里跑通可以把https整段注釋掉后面再補證書也來得及。data_volume是鏡像存儲目錄務必預留出比離線包本身大三倍以上的磁盤空間Harbor 的 registry 存儲層和數(shù)據(jù)庫都會寫在這里。改完配置下一步就交給install.sh。它內部先跑prepare生成 compose 文件再docker load加載替換后的鏡像歸檔最后啟動全部容器。離線環(huán)境里可以先把外部組件關掉比如./install.sh --with-trivy這種參數(shù)在沒有外網(wǎng)、無法更新漏洞數(shù)據(jù)庫的階段先不啟用更穩(wěn)妥。3.4 跑 install.sh 并驗證三個關鍵狀態(tài)執(zhí)行安裝需要 root 權限或者把當前用戶加入 docker 組。直接跑sudo ./install.sh腳本輸出的最后一行如果出現(xiàn)類似Harbor has been installed and started successfully的內容說明安裝主體完成。只看到這行還不夠我用三條命令做啟動驗證docker compose ps curl -k https://192.168.10.20/api/v2.0/health docker login 192.168.10.20 -u admin -p Harbor12345docker compose ps看所有容器是不是處于 Up 狀態(tài)curl打/api/v2.0/health返回{status:healthy}才算服務就緒docker login是鏡像上傳前的最后一道驗證登錄成功了說明 registry、portal、db、nginx 這一整條鏈路是通的。第一次啟動后還可以把install.sh的日志留底后續(xù)排查容器重啟問題時省得反復翻docker logs。ARM64 環(huán)境里docker-compose.yml由prepare生成鏡像 tag 固定跟隨 v2.13.1如果出現(xiàn)某個容器反復 Restarting多半還是鏡像架構或存儲權限問題這一塊放到下一章專門說。4. ARM64 離線部署 Harbor 的五個硬坑現(xiàn)象、原因和解決辦法過程中踩過的坑基本可以分成長這樣五類每一條都按“現(xiàn)象 → 原因 → 解決”的順序拆開方便后面照著排查。4.1 docker load 時報 “no matching manifest for linux/arm64”現(xiàn)象在 ARM64 機器上執(zhí)行docker load -i harbor.v2.13.1.tar.gzDocker 直接報no matching manifest for linux/arm64 in the manifest list entries。原因鏡像歸檔是 amd64 的 manifestDocker 嘗試解出當前平臺的鏡像實例找不到 arm64 的匹配項。這個問題在替換前最容易發(fā)生原因是網(wǎng)上很多人下載的“ARM64 版”實際是把官方 amd64 離線包改名重新打包沒有真正替換過鏡像歸檔。解決不要在這里做任何繞過老老實實按第 3.2 節(jié)的方式導出 arm64 鏡像歸檔再替換。如果改文件名的思路已經(jīng)進行到一半可以用docker manifest inspect goharbor/harbor-core:v2.13.1查看遠端鏡像的 platform 列表確認arm64/v8存在然后重新在 ARM64 機器上 pull 和 save。4.2 install.sh 卡在拉取鏡像而不是使用本地離線歸檔現(xiàn)象sudo ./install.sh執(zhí)行到一半日志顯示Pulling goharbor/harbor-core:v2.13.1內網(wǎng)環(huán)境里網(wǎng)絡不通就一直卡在那。原因install.sh加載離線包后docker compose up如果發(fā)現(xiàn)某個鏡像在本地不存在Compose 會退到默認行為去遠程倉庫拉取。這通常意味著docker load階段沒有真正加載成功最常見的是harbor.v2.13.1.tar.gz文件名不對或者docker load因為磁盤空間不足而中止。解決先看 install.sh 前面幾行日志確認docker load是否出現(xiàn)Loaded image的輸出。沒有輸出就手動執(zhí)行docker load -i harbor.v2.13.1.tar.gz看完整報錯??臻g不足時df -h會看到根分區(qū)或 docker>setenforce 0 sudo ./install.sh如果生產(chǎn)環(huán)境不能關 SELinux更精細的做法是把data_volume、日志目錄放到固定路徑再用chcon -R -t container_file_t /data/harbor設置正確的上下文。也可以在所有容器啟動前創(chuàng)建一個/data/harbor目錄并寫成屬主屬組都是 10000很多 Harbor 容器進程是以 UID 10000 運行的這是我在踩坑后才檢查到的位置。4.4 數(shù)據(jù)目錄容量判斷偏差離線包解壓半路中斷現(xiàn)象docker load執(zhí)行到一半中斷報no space left on device或者磁盤明明夠但install.sh生成的日志目錄寫入失敗。原因離線包harbor.v2.13.1.tar.gz看著只有 1GB 多但這是 gzip 壓縮后的體積docker load解壓后占用接近原始層體積通常翻倍。再加上data_volume里 registry 的存儲目錄又需要一份空間很多人只按壓縮包體積規(guī)劃磁盤裝上才發(fā)現(xiàn)不夠。解決規(guī)劃容量時按離線包解壓后的 3 倍預留。檢查時不要只盯一個分區(qū)/、/var/lib/docker、/data可能是三個不同分區(qū)。docker info | grep Docker Root Dir可以看到 docker>{ insecure-registries: [192.168.10.20] }然后重啟 docker。完整操作順序是先修改daemon.json執(zhí)行systemctl restart docker再docker login 192.168.10.20。生產(chǎn)環(huán)境不要一直用 insecure 模式正確做法是自建 CA把 CA 證書分發(fā)給客戶端并在daemon.json里指向私有 registry 地址和證書。ARM64 的客戶端機器同樣可以在/etc/docker/certs.d/192.168.10.20/下放ca.crtDocker 會自動信任這對內網(wǎng)大量 ARM64 客戶端分批配置時更可控。5. 落地前最后一道工序驗證 ARM64 鏡像清單并按批導入業(yè)務鏡像安裝成功只是第一步真正的交付還要把業(yè)務鏡像送進 Harbor。我習慣在部署前先驗證鏡像源是否真的支持 ARM64然后才安排批量導入。5.1 用 docker buildx imagetools 在離線前核對所有平臺在能聯(lián)網(wǎng)的機器上用docker buildx imagetools inspect檢查遠端鏡像的 platform 列表比直接 pull 更省流量。docker buildx imagetools inspect goharbor/harbor-core:v2.13.1輸出里的Platforms字段會列出linux/arm64/v8、linux/amd64等。這一步能在離線操作前就把“這個鏡像支不支持 ARM64 機器”的黑匣子打開避免拉到不帶 arm64 的鏡像后才發(fā)現(xiàn)。對于業(yè)務系統(tǒng)鏡像同樣可以用這個命令驗一遍特別是那些基礎鏡像是 alpine 或 debian 的一般都有多架構支持但一旦基礎鏡像是第三方定制的 x86-only 二進制就得聯(lián)系上游重新提供。5.2 在目標機上批量 load 業(yè)務鏡像并推入 Harbor離線業(yè)務鏡像通常也是用docker save導出的。在 ARM64 目標機上加載一套鏡像再推入 Harbor命令如下docker load -i business-images.tar.gz docker tag my-app:arm64-v1.0 192.168.10.20/library/my-app:arm64-v1.0 docker push 192.168.10.20/library/my-app:arm64-v1.0參數(shù)說明docker load會原樣還原 save 時的 image tagdocker tag在本地給鏡像增加一個帶 Harbor 地址的 tag推送時 Docker 才知道要去哪個 registrydocker push前確保已經(jīng)用 admin 賬號或新建的項目賬號做過docker login。這里有個細節(jié)離線導入的鏡像如果架構不對docker load不會報錯要等docker run才會暴露所以我建議推之前先docker image inspect my-app:arm64-v1.0 --format {{.Architecture}}確認一次。5.3 一張部署檢查表和我的固定動作檢查項驗證結果離線包鏡像歸檔架構docker image inspect輸出linux/arm64install.sh 完成后容器狀態(tài)docker compose ps全部 UpHarbor API 健康curl /api/v2.0/health返回 healthy磁盤空間style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />