構建依賴映象

要求: Docker Compose 2.22.0 及更高版本

為了減少推送/拉取時間和映象大小,Compose 應用程式的一個常見做法是讓服務儘可能共享基礎層。通常會為所有服務選擇相同的作業系統基礎映象。但當你的映象共享相同的系統包時,你還可以進一步共享映象層。此時需要解決的挑戰是避免在所有服務的 Dockerfile 中重複完全相同的 Dockerfile 指令。

為了說明,本頁假設你希望所有服務都使用 alpine 基礎映象構建並安裝系統包 openssl

多階段 Dockerfile

推薦的方法是將共享宣告分組到一個 Dockerfile 中,並使用多階段功能,以便服務映象可以從此共享宣告構建。

Dockerfile

FROM alpine as base
RUN /bin/sh -c apk add --update --no-cache openssl

FROM base as service_a
# build service a
...

FROM base as service_b
# build service b
...

Compose 檔案

services:
  a:
     build:
       target: service_a
  b:
     build:
       target: service_b

將另一個服務的映象用作基礎映象

一個流行的模式是將一個服務的映象作為基礎映象在另一個服務中使用。由於 Compose 不解析 Dockerfile,它無法自動檢測服務之間的這種依賴關係,從而無法正確地排序構建執行。

a.Dockerfile

FROM alpine
RUN /bin/sh -c apk add --update --no-cache openssl

b.Dockerfile

FROM service_a
# build service b

Compose 檔案

services:
  a:
     image: service_a 
     build:
       dockerfile: a.Dockerfile
  b:
     image: service_b
     build:
       dockerfile: b.Dockerfile

傳統的 Docker Compose v1 用於按順序構建映象,這使得此模式可以開箱即用。Compose v2 使用 BuildKit 來最佳化構建並並行構建映象,因此需要明確宣告依賴關係。

推薦的方法是將依賴的基礎映象宣告為額外的構建上下文

Compose 檔案

services:
  a:
     image: service_a
     build: 
       dockerfile: a.Dockerfile
  b:
     image: service_b
     build:
       dockerfile: b.Dockerfile
       additional_contexts:
         # `FROM service_a` will be resolved as a dependency on service "a" which has to be built first
         service_a: "service:a"

使用 additional_contexts 屬性,你可以引用由另一個服務構建的映象,而無需顯式命名它

b.Dockerfile


FROM base_image  
# `base_image` doesn't resolve to an actual image. This is used to point to a named additional context

# build service b

Compose 檔案

services:
  a:
     build: 
       dockerfile: a.Dockerfile
       # built image will be tagged <project_name>_a
  b:
     build:
       dockerfile: b.Dockerfile
       additional_contexts:
         # `FROM base_image` will be resolved as a dependency on service "a" which has to be built first
         base_image: "service:a"

使用 Bake 構建

使用 Bake 可以讓你傳遞所有服務的完整構建定義,並以最有效的方式協調構建執行。

要啟用此功能,請在你的環境中設定 COMPOSE_BAKE=true 環境變數來執行 Compose。

$ COMPOSE_BAKE=true docker compose build
[+] Building 0.0s (0/1)                                                         
 => [internal] load local bake definitions                                 0.0s
...
[+] Building 2/2 manifest list sha256:4bd2e88a262a02ddef525c381a5bdb08c83  0.0s
 ✔ service_b  Built                                                        0.7s 
 ✔ service_a  Built    

你還可以透過編輯 $HOME/.docker/config.json 配置檔案將 Bake 選擇為預設的 builder

{
  ...
  "plugins": {
    "compose": {
      "build": "bake"
    }
  }
  ...
}
頁面選項