使用 Bake 建置 Compose 專案

本指南探討如何使用 Bake 為包含多個服務的 Docker Compose 專案建置映像檔。

Docker Buildx Bake 是一個建置協調工具,它能為您的建置過程提供宣告式配置,就像 Docker Compose 定義執行時期堆疊一樣。對於使用 Docker Compose 來啟動本機開發服務的專案,Bake 提供了一種無縫擴展專案以實現生產級建置配置的方法。

先決條件

本指南假設您熟悉以下內容

導覽

本指南將使用 dvdksn/example-voting-app 儲存庫作為範例,說明如何將使用 Docker Compose 的單一儲存庫(monorepo)透過 Bake 進行擴展。

$ git clone https://github.com/dvdksn/example-voting-app.git
$ cd example-voting-app

此儲存庫使用 Docker Compose 在 compose.yaml 檔案中定義執行應用程式所需的執行時期配置。此應用程式包含以下服務:

服務描述
vote一個 Python 前端網頁應用程式,讓您可以在兩個選項中進行投票。
result一個 Node.js 網頁應用程式,用來即時顯示投票結果。
worker一個 .NET 背景程式,負責處理投票並將其儲存到資料庫中。
db一個由 Docker 磁碟區(volume)支援的 Postgres 資料庫。
redis一個用來收集新投票的 Redis 實例。
seed一個測試用的工具容器,用於使用模擬資料來填入資料庫。

voteresultworker 服務是從此儲存庫中的程式碼建置而成,而 dbredis 則使用 Docker Hub 上現有的 Postgres 和 Redis 映像檔。seed 服務是一個工具,它會對前端服務發送請求以填充資料庫,僅供測試使用。

使用 Compose 建置

當您啟動 Docker Compose 專案時,任何定義了 build 屬性的服務都會在服務啟動前自動建置。以下是範例儲存庫中 vote 服務的建置配置:

compose.yaml
services:
  vote:
    build:
      context: ./vote # Build context
      target: dev # Dockerfile stage

voteresultworker 服務都指定了建置配置。執行 docker compose up 將會觸發這些服務的建置。

您知道嗎?您也可以僅使用 Compose 來建置服務映像檔。docker compose build 指令讓您可以使用 Compose 檔案中指定的建置配置來觸發建置。例如,若要使用此配置建置 vote 服務,請執行:

$ docker compose build vote

省略服務名稱即可一次建置所有服務:

$ docker compose build

當您只需要建置映像檔而無需執行服務時,docker compose build 指令非常有用。

Compose 檔案格式支援多種屬性來定義您的建置配置。例如,若要指定映像檔的標籤名稱,請在服務上設定 image 屬性。

services:
  vote:
    image: username/vote
    build:
      context: ./vote
      target: dev
    #...

  result:
    image: username/result
    build:
      context: ./result
    #...

  worker:
    image: username/worker
    build:
      context: ./worker
    #...

執行 docker compose build 會建立三個服務映像檔,並帶有完整的映像檔名稱,您可以將其推送到 Docker Hub。

build 屬性支援廣泛的配置選項。然而,建置生產級映像檔的需求通常與本機開發用的映像檔不同。為了避免在 Compose 檔案中堆疊不適合本機建置的配置,建議您將生產建置與本機建置分開,改用 Bake 來建置發佈用的映像檔。這種方法實現了關注點分離:使用 Compose 進行本機開發,並使用 Bake 進行生產級建置,同時仍能重用服務定義與基礎建置配置。

使用 Bake 建置

與 Compose 一樣,Bake 會從配置檔案中解析專案的建置定義。Bake 支援 HashiCorp 設定語言 (HCL)、JSON 和 Docker Compose YAML 格式。當您將 Bake 與多個檔案一起使用時,它會尋找並合併所有適用的配置檔案,形成一個統一的建置配置。Compose 檔案中定義的建置選項會由 Bake 檔案中指定的選項進行擴展,或在某些情況下進行覆蓋。

下一節將探討如何使用 Bake 來擴展 Compose 檔案中定義的生產建置選項。

查看建置設定

Bake 會自動根據服務的 build 屬性建立建置配置。使用 --print 旗標,可以查看給定 Compose 檔案的 Bake 建置配置。此旗標會評估建置配置並以 JSON 格式輸出建置定義。

$ docker buildx bake --print

JSON 格式的輸出會顯示即將執行的群組(group),以及該群組的所有目標(target)。群組是建置的集合,而目標則代表單一建置。

{
  "group": {
    "default": {
      "targets": [
        "vote",
        "result",
        "worker",
        "seed"
      ]
    }
  },
  "target": {
    "result": {
      "context": "result",
      "dockerfile": "Dockerfile",
    },
    "seed": {
      "context": "seed-data",
      "dockerfile": "Dockerfile",
    },
    "vote": {
      "context": "vote",
      "dockerfile": "Dockerfile",
      "target": "dev",
    },
    "worker": {
      "context": "worker",
      "dockerfile": "Dockerfile",
    }
  }
}

如您所見,Bake 自動建立了一個包含四個目標的 default 群組:

  • seed
  • vote
  • result
  • worker

此群組是根據您的 Compose 檔案自動建立的;它包含所有含有建置配置的服務。若要使用 Bake 建置此服務群組,請執行:

$ docker buildx bake

自訂建置群組

首先,重新定義 Bake 執行的預設建置群組。目前的預設群組包含一個 seed 目標——這是一個僅用於向資料庫填入模擬資料的 Compose 服務。由於此目標不會產生生產映像檔,因此無需將其包含在建置群組中。

若要自訂 Bake 使用的建置配置,請在儲存庫根目錄中建立一個新檔案,與您的 compose.yaml 檔案並列,命名為 docker-bake.hcl

$ touch docker-bake.hcl

開啟 Bake 檔案並新增以下配置:

docker-bake.hcl
group "default" {
  targets = ["vote", "result", "worker"]
}

儲存檔案並再次列印您的 Bake 定義:

$ docker buildx bake --print

JSON 輸出顯示 default 群組現在僅包含您關心的目標。

{
  "group": {
    "default": {
      "targets": ["vote", "result", "worker"]
    }
  },
  "target": {
    "result": {
      "context": "result",
      "dockerfile": "Dockerfile",
      "tags": ["username/result"]
    },
    "vote": {
      "context": "vote",
      "dockerfile": "Dockerfile",
      "tags": ["username/vote"],
      "target": "dev"
    },
    "worker": {
      "context": "worker",
      "dockerfile": "Dockerfile",
      "tags": ["username/worker"]
    }
  }
}

在這裡,每個目標的建置配置(context、tags 等)都是從 compose.yaml 檔案中獲取的。群組則是透過 docker-bake.hcl 檔案定義的。

自訂目標

目前的 Compose 檔案將 dev 階段定義為 vote 服務的建置目標。這對於在本機開發中執行的映像檔來說是合適的,因為 dev 階段包含額外的開發依賴項與配置。然而,對於生產映像檔,您會希望改為指向 final 階段。

若要修改 vote 服務使用的目標階段,請將以下配置新增至 Bake 檔案中:

target "vote" {
  target = "final"
}

當您使用 Bake 執行建置時,這會覆蓋 Compose 檔案中指定的 target 屬性。Compose 檔案中的其他建置選項(tag、context)保持不變。您可以透過執行 docker buildx bake --print vote 來檢查 vote 目標的建置配置進行驗證。

{
  "group": {
    "default": {
      "targets": ["vote"]
    }
  },
  "target": {
    "vote": {
      "context": "vote",
      "dockerfile": "Dockerfile",
      "tags": ["username/vote"],
      "target": "final"
    }
  }
}

額外的建置功能

生產級建置的特性通常與開發建置不同。以下是您可能希望為生產映像檔新增的幾項功能:

多平台
對於本機開發,您只需要為您的本機平台建置映像檔,因為這些映像檔只會在您的機器上執行。但對於推送到登錄檔(registry)的映像檔,建置多平台映像檔(特別是 arm64 和 amd64)通常是個好主意。
證明
證明 (Attestations) 是附加在映像檔上的資訊清單,用於描述映像檔是如何建立的以及包含哪些組件。將證明附加到您的映像檔有助於確保您的映像檔遵循軟體供應鏈的最佳實踐。
註解
註解 (Annotations) 為映像檔提供描述性元資料。使用註解來記錄任意資訊並將其附加到您的映像檔,這有助於使用者和工具了解來源、內容以及如何使用該映像檔。
提示

為什麼不直接在 Compose 檔案中定義這些額外的建置選項呢?

Compose 檔案格式中的 build 屬性並不支援所有的建置功能。此外,某些功能(例如多平台建置)會大幅增加建置服務所需的時間。對於本機開發,最好保持建置步驟簡單快速,將這些進階功能留給發佈建置。

若要將這些屬性新增至您使用 Bake 建置的映像檔,請更新 Bake 檔案如下:

group "default" {
  targets = ["vote", "result", "worker"]
}

target "_common" {
  annotations = ["org.opencontainers.image.authors=username"]
  platforms = ["linux/amd64", "linux/arm64"]
  attest = [
    "type=provenance,mode=max",
    "type=sbom"
  ]
}

target "vote" {
  inherits = ["_common"]
  target = "final"
}

target "result" {
  inherits = ["_common"]
}

target "worker" {
  inherits = ["_common"]
}

這定義了一個新的 _common 目標,用於定義可重複使用的建置配置,以新增多平台支援、註解和證明到您的映像檔中。此可重複使用的目標將被建置目標繼承。

透過這些變更,使用 Bake 建置專案會為 linux/amd64linux/arm64 架構產生三組多平台映像檔。每個映像檔都裝飾有作者註解,以及 SBOM 和溯源證明記錄。

總結

本指南中示範的模式為管理使用 Docker Compose 專案中的生產級 Docker 映像檔提供了一種有效的方法。使用 Bake 可以讓您存取 Buildx 和 BuildKit 的所有強大功能,並有助於以合理的方式區分您的開發與建置配置。

延伸閱讀

若需更多關於如何使用 Bake 的資訊,請參閱以下資源:

© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.