如何使用 Docker Buildx Bake 創建複雜的鏡像構建管道

已發表: 2022-08-10

顯示 Docker 徽標的圖形

docker buildx命令組使用 BuildKit 來公開高級鏡像構建功能。 烘焙構建是一種高級功能,可用於定義自動構建管道。 它們使您可以從單個構建操作中生成多個圖像。

當您想要發布圖像的不同變體或併行構建多個鏈接項目時,烘焙工作流程很有幫助。 在本文中,我們將介紹docker buildx bake的主要功能以及如何使用它們來簡化複雜的構建。

入門

docker buildx bake命令執行多個構建“目標”,每個構建“目標”都會生成一個容器映像。 目標盡可能並行運行,以最大限度地提高性能。 目標也可以直接引用前任來創建順序管道。

可以使用幾種不同的機制定義構建目標,包括現有的 Docker Compose 文件。 Buildx 將自動構建文件中標識的所有圖像。

當您在 JSON 或 HCL 文件中列出構建目標時,會公開更多高級功能。 這些支持變量、函數和值插值來自定義您的構建。

buildx bake命令按順序查找以下文件:

  • docker-compose.yml
  • docker-compose.yaml
  • docker-bake.json
  • docker-bake.override.json
  • docker-bake.hcl
  • docker-bake.override.hcl

您可以使用-f命令標誌指定不同的文件。

構建目標

構建目標封裝了與您的構建相關的所有配置。 它們包括詳細信息,例如

  • 要構建的 Dockerfile 的路徑
  • 構建上下文路徑,定義 Dockerfile 中可用的內容
  • 附加到輸出圖像的標籤和標籤
  • 為其生成圖像的平台。

文檔中提供了支持的配置字段的完整列表。 以前,您可能已經將這些設置作為命令行標誌提供給docker buildx build (甚至是普通的 docker docker build ),迫使您每次都記住正確的值。 使用buildx bake ,您可以通過在受版本控制的烘焙文件中定義它們來可靠地使用相同的值。

這是定義單個構建目標docker-bake.hcl命令的簡單示例:

 target "default" { dockerfile = "app/Dockerfile" contexts = { app = "app/src" shared = "shared-components/src" } tags = ["my-app:latest", "docker.io/my-org/my-app:latest"] }

使用此烘焙文件運行docker buildx bake buildx bake 將從您的工作目錄加載app/Dockerfile Dockerfile。 它可以訪問app/srcshared-components/src目錄作為構建上下文。 生成的圖像將被分配兩個標籤。

運行docker buildx bake時會自動構建default目標。 您還可以定義可以按需構建的命名目標:

 target "app" { // ... }
 $ docker buildx bake app

使用多個目標

您可以通過在烘焙文件中將其定義為新目標來同時構建另一個圖像:

 group "default" { targets = ["app", "api"] } target "app" { dockerfile = "app/Dockerfile" contexts = { app = "app/src" shared = "shared-components/src" } tags = ["my-app:latest", "docker.io/my-org/my-app:latest"] } target "api" { dockerfile = "api/Dockerfile" contexts = { src = "api/src" } tags = ["my-api:latest", "docker.io/my-org/my-api:latest"] }

這些圖像可以同時構建,因為它們嵌套在一個組中。 每次運行docker buildx bake命令時, apiapp映像將並行構建,因為default組是自動選擇的。 您可以使用與上述命名目標示例類似的命名組。

構建目標繼承

構建目標可以相互繼承以重用配置。 這可能有用的一種情況涉及需要為不同環境定制的圖像。 您可能希望將額外的配置文件添加到旨在用於開發的圖像變體中。 這是演示此模型docker-bake.hcl

 group "default" { targets = ["backend", "backend-dev"] } target "backend" { dockerfile = "backend/Dockerfile" contexts = { src = "api/src" config = "api/config" } tags = ["backend:latest"] } target "backend-dev" { inherits = ["backend"] contexts = { config = "api/config-dev" } tags = ["backend:dev"] }

backend-dev目標繼承了backend目標的所有屬性,但覆蓋了config上下文並應用了不同的標籤。

您可以通過運行帶有--print標誌的bake命令來預覽合併的文件結構:

 $ docker buildx bake --print ... "backend-dev": { "context": ".", "contexts": { "config": "api/config-dev", "src": "api/src" }, "dockerfile": "backend/Dockerfile", "tags": [ "backend:dev" ] } ...

使用先前的目標作為基礎圖像

有時您可能希望構建目標使用由先前目標創建的映像作為其自己的基礎。 這是多階段構建的替代方案,當您的 Dockerfile 相互依賴但無法合併在一起時,可以使用它,這可能是因為它們存在​​於不同的項目中。

 group "default" { targets = ["org-base-image", "api"] } target "org-base-image" { dockerfile = "docker-base/Dockerfile" tags = ["org-base-image:latest"] } target "api" { dockerfile = "api/Dockerfile" contexts = { base = "target:org-base-image" } tags = ["api:latest"] }

該示例首先構建org-base-image目標。 這可能包含您組織的容器化工作負載常見的一些實用程序。 然後使用org-base-image目標的輸出構建api目標,該目標可作為base構建上下文訪問。 API Dockerfile 現在可以引用基礎鏡像中的內容:

 COPY --from=base /utilities/example /usr/bin/example-utility

這是一種強大的模式,可讓您在鏡像之間創建依賴鏈接,同時維護單獨的 Dockerfile。

在構建時覆蓋目標的屬性

docker buildx bake命令允許您在運行構建時覆蓋目標的屬性:

 $ docker buildx bake --set api.dockerfile="api/Dockerfile-dev"

此示例更改api目標的 Dockerfile。 識別要更改的目標時支持*通配符。 *自己選擇每個目標,而api*將修改所有以api開頭的目標。

設置變量

HCL 文件可以定義您可以在構建目標中引用的變量。 使用variable塊來設置它們:

 variable "TAG" { default = "latest" } group "default" { targets = ["app"] } target "app" { dockerfile = "src/Dockerfile" tags = ["my-app:${TAG}"] }

使用此配置運行docker buildx bake會將app目標標記為my-app:latest 。 您可以在執行命令之前通過設置環境變量來更改TAG變量的值:

 $ TAG=v1 docker buildx bake

您可以使用 HCL 語言的所有變量插值和比較功能來使您的構建目標可重用。 函數也可用於解析和轉換您的值。

概括

Baked Buildx 構建允許您將映像構建配置封裝為文件中定義的“目標”。 當您運行buildx bake時,所有引用目標的圖像都是並行構建的。

目標可以相互繼承並相互依賴。 您還可以使用變量和函數來創建高度複雜且可配置的構建管道。

docker buildx bake命令是一個高級操作,並非在每個工作流程中都需要。 當您創建沒有跨項目依賴關係的簡單圖像時,您不需要使用它。 對於大多數將構建配置保存在docker-compose.yml文件中的用例,使用 docker docker compose build是一種更好的選擇。 當您使用不同的變量、平台、構建上下文和配置覆蓋同時構建多個映像時,應考慮切換到烘焙構建。