使用 Bake 搭配額外上下文

除了定義建構上下文的預設 context 鍵外,每個目標 (target) 還可以使用鍵為 contexts 的映射 (map) 來定義額外的命名上下文。這些值對應到 build 指令中的 --build-context 旗標。

在 Dockerfile 內部,這些上下文可以使用 FROM 指令或 --from 旗標來使用。

支援的上下文值包括:

  • 本機檔案系統目錄
  • 容器映像檔
  • Git URL
  • HTTP URL
  • Bake 檔案中另一個目標的名稱

鎖定 alpine 映像檔版本

Dockerfile
# syntax=docker/dockerfile:1
FROM alpine
RUN echo "Hello world"
docker-bake.hcl
target "app" {
  contexts = {
    alpine = "docker-image://alpine:3.13"
  }
}

使用次要來源目錄

Dockerfile
FROM golang
COPY --from=src . .
docker-bake.hcl
# Running `docker buildx bake app` will result in `src` not pointing
# to some previous build stage but to the client filesystem, not part of the context.
target "app" {
  contexts = {
    src = "../path/to/source"
  }
}

將目標 (Target) 用作建構上下文

若要將一個目標的結果用作另一個目標的建構上下文,請指定帶有 target: 前綴的目標名稱。

baseapp.Dockerfile
FROM scratch
Dockerfile
# syntax=docker/dockerfile:1
FROM baseapp
RUN echo "Hello world"
docker-bake.hcl
target "base" {
  dockerfile = "baseapp.Dockerfile"
}

target "app" {
  contexts = {
    baseapp = "target:base"
  }
}

在大多數情況下,您應該直接使用單個多階段 (multi-stage) Dockerfile 並配置多個目標來達成類似行為。僅在您擁有多個無法輕易合併為一個的 Dockerfile 時,才建議使用此案例。

去重上下文傳輸

注意

自 Buildx 0.17.0 版本起,Bake 會自動針對共享相同上下文的目標進行上下文傳輸去重。除了 Buildx 0.17.0 版本外,建構器 (builder) 必須執行 BuildKit 0.16.0 或更高版本,且 Dockerfile 語法必須為 docker/dockerfile:1.10 或更高版本。

如果您符合這些要求,則無需如本節所述手動去重上下文傳輸。

  • 若要檢查您的 Buildx 版本,請執行 docker buildx version
  • 若要檢查您的 BuildKit 版本,請執行 docker buildx inspect --bootstrap 並查看 BuildKit version 欄位。
  • 若要檢查您的 Dockerfile 語法版本,請查看 Dockerfile 中的 syntax 解析器指令 (parser directive)。如果不存在,預設版本為您當前 BuildKit 版本所附帶的版本。若要明確設定版本,請在 Dockerfile 頂部加入 #syntax=docker/dockerfile:1.10

當您使用群組 (groups) 並行建構目標時,建構上下文會針對每個目標獨立載入。如果群組中的多個目標使用相同的上下文,則該上下文會在每次使用時被傳輸一次。根據您的建構配置,這可能會對建構時間產生顯著影響。例如,假設您有一個定義了以下目標群組的 Bake 檔案:

docker-bake.hcl
group "default" {
  targets = ["target1", "target2"]
}

target "target1" {
  target = "target1"
  context = "."
}

target "target2" {
  target = "target2"
  context = "."
}

在此情況下,當您建構預設群組時,上下文 . 會被傳輸兩次:target1 一次,target2 一次。

如果您的上下文很小,且您使用的是本機建構器,重複傳輸上下文可能不是大問題。但如果您的建構上下文很大,或者您有大量的目標,又或者您是將上下文透過網路傳輸到遠端建構器,那麼上下文傳輸就會成為效能瓶頸。

為了避免多次傳輸相同的上下文,您可以定義一個僅載入上下文檔案的命名上下文,並讓每個需要這些檔案的目標引用該命名上下文。例如,下方的 Bake 檔案定義了一個命名目標 ctx,它被 target1target2 同時使用:

docker-bake.hcl
group "default" {
  targets = ["target1", "target2"]
}

target "ctx" {
  context = "."
  target = "ctx"
}

target "target1" {
  target = "target1"
  contexts = {
    ctx = "target:ctx"
  }
}

target "target2" {
  target = "target2"
  contexts = {
    ctx = "target:ctx"
  }
}

命名上下文 ctx 代表一個 Dockerfile 階段,它會從其上下文 (.) 複製檔案。Dockerfile 中的其他階段現在可以引用 ctx 命名上下文,例如使用 --mount=from=ctx 來掛載其檔案。

Dockerfile
FROM scratch AS ctx
COPY --link . .

FROM golang:alpine AS target1
WORKDIR /work
RUN --mount=from=ctx \
    go build -o /out/client ./cmd/client \

FROM golang:alpine AS target2
WORKDIR /work
RUN --mount=from=ctx \
    go build -o /out/server ./cmd/server
© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.