使用 Bake 附加上下文

除了定義構建上下文的主 `context` 鍵外,每個目標還可以使用 `contexts` 鍵定義的對映來定義額外的命名上下文。這些值對映到 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:` 字首指定目標名稱。

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

在大多數情況下,您應該只使用一個具有多個目標的多階段 Dockerfile 來實現類似的行為。僅當您有多個 Dockerfile 無法輕鬆合併為一個時,才建議使用此方法。

去重上下文傳輸

注意

從 Buildx 0.17.0 及更高版本開始,Bake 會自動對共享相同上下文的目標進行上下文傳輸去重。除了 Buildx 0.17.0,構建器還必須執行 BuildKit 0.16.0 或更高版本,並且 Dockerfile 語法必須是 `docker/dockerfile:1.10` 或更高版本。

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

  • 要檢查您的 Buildx 版本,請執行 `docker buildx version`。
  • 要檢查您的 BuildKit 版本,請執行 `docker buildx inspect --bootstrap` 並查詢 `BuildKit version` 欄位。
  • 要檢查您的 Dockerfile 語法版本,請檢查 Dockerfile 中的 `syntax` 解析器指令。如果不存在,則預設為您的當前 BuildKit 版本捆綁的任何版本。要顯式設定版本,請在 Dockerfile 頂部新增 `#syntax=docker/dockerfile:1.10`。

當您使用組並行構建目標時,每個目標的構建上下文是獨立載入的。如果同一上下文被組中的多個目標使用,則該上下文每使用一次就傳輸一次。這可能會對構建時間產生重大影響,具體取決於您的構建配置。例如,假設您有一個 Bake 檔案,它定義了以下目標組

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

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

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

在這種情況下,當您構建預設組時,上下文 `.` 會傳輸兩次:一次用於 `target1`,一次用於 `target2`。

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

為了避免多次傳輸相同的上下文,您可以定義一個只加載上下文檔案的命名上下文,並讓需要這些檔案的每個目標引用該命名上下文。例如,以下 Bake 檔案定義了一個名為 `ctx` 的命名目標,`target1` 和 `target2` 都使用它

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