建指南:讀懂 samples/builder 的 docker buildx bake 流水線)
Istio 示例鏡像構(gòu)建指南讀懂 samples/builder 的 docker buildx bake 流水線【免費下載鏈接】istioConnect, secure, control, and observe services.項目地址: https://gitcode.com/GitHub_Trending/is/istioIstio 倉庫的許多示例bookinfo、helloworld、tcp-echo 等都需要隨發(fā)布流程打制成容器鏡像。本指南聚焦 samples/builder/README.md 及其背后真正起作用的 samples/builder/docker-bake.hcl講清這套集中式鏡像構(gòu)建邏輯如何運作、如何用一條docker buildx bake命令構(gòu)建并推送全部或部分示例鏡像、如何覆蓋鏡像倉庫與目標平臺以及官方鏡像與示例鏡像更新時應(yīng)當遵守的版本維護流程。讀完你既能直接在本地復(fù)現(xiàn)構(gòu)建也能理解 HCL 矩陣配置與多階段構(gòu)建源碼之間的配合關(guān)系。目錄定位為什么需要一個集中的 sample builderIstio 倉庫根目錄下有大量示例應(yīng)用目錄每個示例自身通常帶有 Dockerfile 與對應(yīng)的 K8s YAML。長久以來鏡像構(gòu)建邏輯分散在各示例目錄里容易重復(fù)、不一致。samples/builder目錄的存在就是為了把各種示例的鏡像構(gòu)建邏輯集中起來consolidate things便于統(tǒng)一維護版本、統(tǒng)一打 multi-arch 標簽并推送到統(tǒng)一的鏡像倉庫。需要留意 README 給出的兩個邊界條件仍有一些鏡像使用各自目錄內(nèi)的構(gòu)建配置因此samples/builder覆蓋范圍并不完整——例如多數(shù)傳統(tǒng)示例仍使用各目錄獨立的鏡像打包與 CI 流程本目錄當前采用Docker Buildx BakeHCL作為唯一構(gòu)建入口構(gòu)建邏輯真正落在 docker-bake.hcl 這一個文件中README.md只是操作說明。構(gòu)建配置核心讀透 docker-bake.hcldocker-bake.hcl 全部 45 行定義了整套鏡像矩陣從文件結(jié)構(gòu)可以拆分出三個層次。1. 可變變量可在命令行覆蓋variable HUB { default localhost:5000 } variable PLATFORMS { default linux/amd64,linux/arm64 }HUB鏡像倉庫地址前綴默認localhost:5000即默認推送到本機運行的 registryPLATFORMS目標平臺列表默認同時構(gòu)建linux/amd64與linux/arm64兩種架構(gòu)。兩個變量在 bake 時都可以通過--set或環(huán)境方式覆蓋詳見下文構(gòu)建與推送一節(jié)。2. 鏡像清單 images當前清單包含三組鏡像其中 helloworld 的 v1/v2 共享同一份源碼../helloworld/src僅通過構(gòu)建參數(shù)service_version區(qū)分images [ { name tcp-echo-server source ../tcp-echo/src tags [1.3, latest] }, { name examples-helloworld-v1 source ../helloworld/src args { service_version v1 } tags [1.0, latest] }, { name examples-helloworld-v2 source ../helloworld/src args { service_version v2 } tags [1.0, latest] }, ]每個條目包含四個字段其作用分別是字段含義當前取值示例name鏡像名不含倉庫前綴tcp-echo-server、examples-helloworld-v1/v2source構(gòu)建上下文相對 docker-bake.hcl 的路徑../tcp-echo/src、../helloworld/srcargs傳給 Dockerfile 的ARG構(gòu)建參數(shù)service_version v1tags版本標簽列表除語義化版本外通常帶latest[1.3, latest]source字段體現(xiàn)了本倉庫真實的目錄布局三個鏡像的實際構(gòu)建上下文分別指向 samples/tcp-echo/src 與 samples/helloworld/src說明 builder 目錄本身只是編排層鏡像源碼仍留在各自的示例目錄中。3. default target矩陣展開生成最終 targettarget default { matrix { item images } name item.name context ${item.source} tags [ for x in setproduct([HUB], item.tags) : join(/${item.name}:, x) ] args lookup(item, args, {}) platforms split(,, lookup(item, platforms, PLATFORMS)) }這段 HCL 的關(guān)鍵機制如下matrix.item images把上面的鏡像清單作為矩陣輸入Buildx 會為清單中每一項自動生成一個獨立的 bake targettarget 名稱即item.namecontext ${item.source}每個 target 使用各自聲明的構(gòu)建上下文目錄標簽的生成使用setproduct將[HUB]與該項的tags做笛卡爾積再用join(/${item.name}:, x)拼出完整標簽例如默認HUB下 tcp-echo-server 會被打上localhost:5000/tcp-echo-server:1.3localhost:5000/tcp-echo-server:latestlookup(item, args, {})與lookup(item, platforms, PLATFORMS)表示當某個條目未顯式聲明對應(yīng)字段時分別回落為無構(gòu)建參數(shù)與全局PLATFORMS默認值。這一設(shè)計使后續(xù)新增鏡像只需向images清單追加一個條目即可自動獲得矩陣構(gòu)建、多架構(gòu)支持與統(tǒng)一打標簽?zāi)芰o需復(fù)制粘貼 target。鏡像背后的源碼兩個示例的構(gòu)建上下文集中構(gòu)建并不代表鏡像實現(xiàn)集中最終成果由各示例目錄中的 Dockerfile 與程序源碼決定理解它們有助于排查構(gòu)建失敗或按需裁剪鏡像。helloworldPython 構(gòu)建期參數(shù)區(qū)分版本samples/helloworld/src/Dockerfile 基于python:3.12.1-slim將app.py與固定哈希的requirements.txt拷貝進/opt/microservices安裝依賴并額外裝入curl作為可選的客戶端工具。其中與 bake 矩陣對接的關(guān)鍵行ARG service_version ENV SERVICE_VERSION${service_version:-v1} CMD [gunicorn, -b, [::]:5000, app:app, -k, gevent]同一份源碼通過service_version這一個 ARG 產(chǎn)出 v1/v2 兩個鏡像鏡像運行后會根據(jù)該環(huán)境變量返回不同版本的響應(yīng)——這正是 helloworld 示例用于演示金絲雀發(fā)布把流量在 v1/v2 間灰度切分的基礎(chǔ)默認監(jiān)聽[::]:5000TCP6若在 K8s Pod 中需要強制 IPv4可在 Deployment 的 command 中覆蓋為[gunicorn, -b, [0.0.0.0]:5000, app:app, -k, gevent]。tcp-echo多階段構(gòu)建產(chǎn)出精簡靜態(tài)鏡像samples/tcp-echo/src/Dockerfile 使用經(jīng)典的兩階段構(gòu)建第一階段基于golang:1.22編譯第二階段從scratch起步僅拷貝靜態(tài)二進制FROM golang:1.22 AS builder WORKDIR /go/src/istio.io/tcp-echo-server/ COPY main.go . RUN CGO_ENABLED0 GOOSlinux go build -ldflags -extldflags -static -s -w -o tcp-echo main.go FROM scratch COPY --frombuilder /go/src/istio.io/tcp-echo-server/tcp-echo . ENTRYPOINT [ /bin/tcp-echo ] CMD [ 9000, hello ]CGO_ENABLED0關(guān)閉 CGO 并靜態(tài)鏈接保證產(chǎn)物能在無 glibc 的scratch中運行鏡像體積最小化從 samples/tcp-echo/src/main.go 可見程序邏輯通過命令行接收逗號分隔的端口列表與響應(yīng)前綴每收到一行輸入就回顯prefix 原始數(shù)據(jù)Dockerfile 的默認CMD對應(yīng)監(jiān)聽 9000 端口、前綴為 hello該行為與 tcp-echo 示例 YAML 的用途完全匹配——它是 Istio 官方向?qū)е醒菔?TCP 流量路由v1/v2 端口分流的主要樣例。構(gòu)建與推送示例鏡像本地測試README 中給出的核心命令是docker buildx bake --push該命令會構(gòu)建全部鏡像并推送。完整的行為由 docker-bake.hcl 決定包括默認推送目標為localhost:5000因此你需要在構(gòu)建機上先運行一個本地 registry例如docker run -d -p 5000:5000 --name registry registry:2才能讓--push成功默認同時構(gòu)建linux/amd64,linux/arm64需要 docker buildx 已配置好支持多架構(gòu)的 builder如docker-containerdriver否則會退回單平臺或報錯。兩個默認值都可以覆蓋# 推送到其它本地/私有倉庫 HUBmyregistry.example.com:5000 docker buildx bake --push # 僅構(gòu)建單一架構(gòu)加快本地迭代 HUBlocalhost:5000 PLATFORMSlinux/amd64 docker buildx bake --push從 docker-bake.hcl 的實現(xiàn)看HUB與PLATFORMS是通過 HCL 變量注入的tags展開時引用[HUB]platforms展開時把PLATFORMS按逗號切分因此在 bake 命令前以VARvalue形式賦值即可覆蓋 HCL 中的 default。只構(gòu)建部分鏡像并非每次都需要全量構(gòu)建可以顯式點名部分 targetdocker buildx bake --push examples-helloworld-v1 tcp-echo-server由于defaulttarget 采用矩陣展開target 名就等于 images 清單里的name字段因此上例只構(gòu)建并推送 helloworld v1 與 tcp-echo-server 兩個鏡像適合在修改了某個示例源碼后做定向驗證避免把整個矩陣重新跑一遍。更新示例鏡像版本的流程當示例源碼或依賴發(fā)生變化、需要發(fā)布新鏡像時README 明確了兩個動作二者缺一不可在 docker-bake.hcl 的tags配置中遞增版本。以 tcp-echo-server 為例當前標簽為[1.3, latest]若本次要發(fā)新版本應(yīng)改為[1.4, latest]這類新版本號同時保持latest指向最新構(gòu)建同步更新引用該鏡像的示例 YAML。倉庫中 Deployment 等編排文件里硬編碼了鏡像地址與 tag例如 samples/helloworld/helloworld.yaml 中寫有image: registry.istio.io/release/examples-helloworld-v1:1.0第 36 行與 v2 對應(yīng)的:1.0第 65 行。這些 tag 必須與 docker-bake.hcl 中聲明的 tag 保持一致否則發(fā)布到鏡像倉庫的新版本不會被示例默認引用。本質(zhì)上tags列表與 K8s YAML 的image:字段共同構(gòu)成鏡像發(fā)布約定二者需要成對更新這也是 README 特別提醒更新鏡像時還要更新示例 YAML的原因。構(gòu)建官方發(fā)布鏡像的注意事項官方發(fā)布流程與本地測試流程的唯一差別是倉庫前綴HUBregistry.istio.io/release docker buildx bake --push此時所有鏡像將被推送至 Istio 官方發(fā)布倉庫例如 helloworld v1 會被打上registry.istio.io/release/examples-helloworld-v1:1.0之類的完整標簽與上面提到的示例 YAML 引用地址對應(yīng)。README 特別強調(diào)了一個操作紀律每個鏡像最好只在官方倉庫發(fā)布一次以避免意外覆蓋已經(jīng)存在的既有鏡像。原因在于一旦某個 tag尤其latest被發(fā)布后續(xù)任何非預(yù)期的重新構(gòu)建都可能向該 tag 推送內(nèi)容不同、無法追溯的鏡像破壞可復(fù)現(xiàn)性與供應(yīng)鏈可審計性。因此執(zhí)行官方構(gòu)建前應(yīng)仔細核對tags確認版本號確實需要新增/變更再對目標鏡像執(zhí)行一次構(gòu)建。局限性與適用前提在使用這套構(gòu)建方案時請記住以下事實約束均來自倉庫現(xiàn)狀samples/builder目前管理的鏡像只有 helloworldv1/v2與 tcp-echo-server 三類bookinfo、httpbin、sleep 等其它示例鏡像仍由各自目錄內(nèi)的 Dockerfile 與構(gòu)建腳本維護不在本 bake 矩陣內(nèi)全部構(gòu)建邏輯基于 Docker Buildx BakeHCL因此環(huán)境需要具備較新的 Docker 與 buildx 插件且--push依賴已運行的 registry若在離線或受限網(wǎng)絡(luò)環(huán)境構(gòu)建需要注意 helloworld 基礎(chǔ)鏡像與 pip 依賴的拉取requirements.txt 采用--require-hashes固定哈希安裝tcp-echo 則依賴 Go 工具鏈鏡像。相關(guān)文件速查構(gòu)建編排入口samples/builder/README.md、samples/builder/docker-bake.hclhelloworld 鏡像上下文samples/helloworld/src/Dockerfile、samples/helloworld/src/app.py、samples/helloworld/helloworld.yamltcp-echo 鏡像上下文samples/tcp-echo/src/Dockerfile、samples/tcp-echo/src/main.go、samples/tcp-echo/tcp-echo.yaml掌握 samples/builder/docker-bake.hcl 的矩陣寫法后為倉庫新增一個示例鏡像的成本極低只需向images清單追加一條帶name、source、tags的記錄如需版本差異化再加argsdefaulttarget 就會自動完成多架構(gòu)構(gòu)建、倉庫前綴拼接與打標簽工作再用文中命令執(zhí)行構(gòu)建推送、并按版本 示例 YAML成對更新的流程完成發(fā)布即可。【免費下載鏈接】istioConnect, secure, control, and observe services.項目地址: https://gitcode.com/GitHub_Trending/is/istio創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考