使用 Bake 建置 Compose 專案

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

Docker Buildx Bake 是一個建置協調工具,可為您的建置啟用宣告式設定,就像 Docker Compose 為定義執行時期堆疊所做的一樣。 對於使用 Docker Compose 啟動服務以進行本地開發的專案,Bake 提供了一種使用生產就緒建置設定無縫擴展專案的方法。

先決條件

本指南假設您熟悉

方向

本指南將使用 dvdksn/example-voting-app 儲存庫作為使用 Docker Compose 的單一儲存庫範例,可以使用 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 worker,用於使用投票並將其儲存在資料庫中。
db由 Docker 磁碟區支援的 Postgres 資料庫。
redis一個收集新投票的 Redis 執行個體。
seed一個用於以模擬資料填充資料庫的工具容器。

`vote`、`result` 和 `worker` 服務是根據此儲存庫中的程式碼建置的,而 `db` 和 `redis` 使用 Docker Hub 中預先存在的 Postgres 和 Redis 映像檔。`seed` 服務是一個工具,它會對前端服務叫用請求以填充資料庫,以進行測試。

使用 Compose 建置

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

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

`vote`、`result` 和 `worker` 服務都已指定建置設定。執行 `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` 屬性自動建立建置設定。使用 Bake 的 `--print` 旗標來檢視給定 Compose 檔案的建置設定。此旗標會評估建置設定並以 JSON 格式輸出建置定義。

$ docker buildx bake --print

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

{
  "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 使用的建置設定,請在儲存庫的根目錄建立一個名為 `docker-bake.hcl` 的新檔案,與您的 `compose.yaml` 檔案一起存放。

$ 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"]
    }
  }
}

在這裡,每個目標的建置設定(上下文、標籤等)都是從 `compose.yaml` 檔案中擷取的。群組由 `docker-bake.hcl` 檔案定義。

自訂目標

Compose 檔案目前將 `dev` 階段定義為 `vote` 服務的建置目標。這適用於您在本地開發中執行的映像檔,因為 `dev` 階段包含額外的開發依賴項和設定。但是,對於生產映像檔,您需要改為以 `final` 映像檔為目標。

要修改 `vote` 服務使用的目標階段,請將以下設定新增至 Bake 檔案

target "vote" {
  target = "final"
}

當您使用 Bake 執行建置時,這會將 Compose 檔案中指定的 `target` 屬性覆蓋為不同的值。Compose 檔案中的其他建置選項(標籤、上下文)保持不變。您可以使用 `docker buildx bake --print vote` 檢查 `vote` 目標的建置設定來驗證

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

額外的建置功能

生產級建置通常與開發建置具有不同的特性。以下是一些您可能想要為生產映像檔新增的範例。

多平台
對於本地開發,您只需要為您的本地平台建置映像檔,因為這些映像檔只會在您的機器上執行。但是,對於推送至登錄的映像檔,通常最好針對多個平台進行建置,尤其是 arm64 和 amd64。
證明
證明 (Attestations) 是附加到映像檔的資訊清單,描述映像檔是如何建立的以及它包含哪些組件。將證明附加到您的映像檔有助於確保您的映像檔遵循軟體供應鏈最佳實務。
註釋 (Annotations)
註釋 (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 的更多資訊,請查看以下資源