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