合併 Compose 檔案

Docker Compose 允許您將一組 Compose 檔案合併和覆蓋在一起,以建立一個組合的 Compose 檔案。

預設情況下,Compose 讀取兩個檔案,compose.yml 和一個可選的 compose.override.yml 檔案。按照慣例,compose.yml 包含您的基本配置。覆蓋檔案可以包含對現有服務的配置覆蓋或全新的服務。

如果服務在兩個檔案中都定義,Compose 會使用下面描述的規則和 Compose 規範 中的規則合併配置。

如何合併多個 Compose 檔案

要使用多個覆蓋檔案,或使用不同名稱的覆蓋檔案,您可以使用預定義的 COMPOSE_FILE 環境變數,或使用 -f 選項指定檔案列表。

Compose 以命令列上指定的順序合併檔案。後續檔案可能會合並、覆蓋或新增到其前身。

例如

$ docker compose -f compose.yml -f compose.admin.yml run backup_db

compose.yml 檔案可能指定 webapp 服務。

webapp:
  image: examples/web
  ports:
    - "8000:8000"
  volumes:
    - "/data"

compose.admin.yml 也可能指定此相同的服務

webapp:
  environment:
    - DEBUG=1

任何匹配的欄位都會覆蓋之前檔案。新值會新增到 webapp 服務配置中

webapp:
  image: examples/web
  ports:
    - "8000:8000"
  volumes:
    - "/data"
  environment:
    - DEBUG=1
    - ANOTHER_VARIABLE=value

重要

當您使用多個 Compose 檔案時,您必須確保檔案中的所有路徑都相對於基本 Compose 檔案(使用 -f 指定的第一個 Compose 檔案)。這是必需的,因為覆蓋檔案不必是有效的 Compose 檔案。覆蓋檔案可以包含少量配置片段。跟蹤服務中哪個片段相對於哪個路徑很困難而且令人困惑,因此為了使路徑更容易理解,所有路徑都必須相對於基本檔案定義。

其他資訊

  • 使用 -f 是可選的。如果沒有提供,Compose 會在工作目錄及其父目錄中搜索 compose.ymlcompose.override.yml 檔案。您必須至少提供 compose.yml 檔案。如果兩個檔案存在於同一目錄級別,Compose 會將它們組合成一個配置。

  • 當您使用多個 Compose 檔案時,檔案中的所有路徑都相對於使用 -f 指定的第一個配置檔案。您可以使用 --project-directory 選項覆蓋此基本路徑。

  • 您可以將 -f-(破折號)一起使用作為檔名,從 stdin 讀取配置。例如

    $ docker compose -f - <<EOF
      webapp:
        image: examples/web
        ports:
         - "8000:8000"
        volumes:
         - "/data"
        environment:
         - DEBUG=1
      EOF
    

    當使用 stdin 時,配置中的所有路徑都相對於當前工作目錄。

  • 您可以使用 -f 標誌指定不在當前目錄中的 Compose 檔案的路徑,無論是從命令列還是透過在您的 shell 或環境檔案中設定 COMPOSE_FILE 環境變數

    例如,如果您執行 Compose Rails 示例,並且在名為 sandbox/rails 的目錄中有一個 compose.yml 檔案。您可以使用類似 docker compose pull 的命令從任何地方獲取 db 服務的 postgres 映象,方法是使用 -f 標誌,如下所示:docker compose -f ~/sandbox/rails/compose.yml pull db

    以下是如何完成的示例

    $ docker compose -f ~/sandbox/rails/compose.yml pull db
    Pulling db (postgres:latest)...
    latest: Pulling from library/postgres
    ef0380f84d05: Pull complete
    50cf91dc1db8: Pull complete
    d3add4cd115c: Pull complete
    467830d8a616: Pull complete
    089b9db7dc57: Pull complete
    6fba0a36935c: Pull complete
    81ef0e73c953: Pull complete
    338a6c4894dc: Pull complete
    15853f32f67c: Pull complete
    044c83d92898: Pull complete
    17301519f133: Pull complete
    dcca70822752: Pull complete
    cecf11b8ccf3: Pull complete
    Digest: sha256:1364924c753d5ff7e2260cd34dc4ba05ebd40ee8193391220be0f9901d4e1651
    Status: Downloaded newer image for postgres:latest
    

合併規則

Compose 將原始服務中的配置複製到本地服務中。如果原始服務和本地服務中都定義了配置選項,則本地值會替換或擴充套件原始值。

對於 imagecommandmem_limit 等單值選項,新值會替換舊值。

原始服務

services:
  myservice:
    # ...
    command: python app.py

本地服務

services:
  myservice:
    # ...
    command: python otherapp.py

結果

services:
  myservice:
    # ...
    command: python otherapp.py

對於多值選項 portsexposeexternal_linksdnsdns_searchtmpfs,Compose 會連線兩組值

原始服務

services:
  myservice:
    # ...
    expose:
      - "3000"

本地服務

services:
  myservice:
    # ...
    expose:
      - "4000"
      - "5000"

結果

services:
  myservice:
    # ...
    expose:
      - "3000"
      - "4000"
      - "5000"

environmentlabelsvolumesdevices 的情況下,Compose 會將條目“合併”在一起,並優先使用本地定義的值。對於 environmentlabels,環境變數或標籤名稱決定使用哪個值

原始服務

services:
  myservice:
    # ...
    environment:
      - FOO=original
      - BAR=original

本地服務

services:
  myservice:
    # ...
    environment:
      - BAR=local
      - BAZ=local

結果

services:
  myservice:
    # ...
    environment:
      - FOO=original
      - BAR=local
      - BAZ=local

volumesdevices 的條目使用容器中的掛載路徑進行合併

原始服務

services:
  myservice:
    # ...
    volumes:
      - ./original:/foo
      - ./original:/bar

本地服務

services:
  myservice:
    # ...
    volumes:
      - ./local:/bar
      - ./local:/baz

結果

services:
  myservice:
    # ...
    volumes:
      - ./original:/foo
      - ./local:/bar
      - ./local:/baz

有關更多合併規則,請參閱 Compose 規範中的 合併和覆蓋

示例

使用多個檔案的一個常見用例是更改開發 Compose 應用程式以適應類似生產環境(可能是生產、預釋出或 CI)。為了支援這些差異,您可以將 Compose 配置拆分成幾個不同的檔案

從定義服務的規範配置的基本檔案開始。

compose.yml

services:
  web:
    image: example/my_web_app:latest
    depends_on:
      - db
      - cache

  db:
    image: postgres:latest

  cache:
    image: redis:latest

在此示例中,開發配置將一些埠公開到主機,將我們的程式碼作為卷掛載,並構建 Web 映象。

compose.override.yml

services:
  web:
    build: .
    volumes:
      - '.:/code'
    ports:
      - 8883:80
    environment:
      DEBUG: 'true'

  db:
    command: '-d'
    ports:
     - 5432:5432

  cache:
    ports:
      - 6379:6379

當您執行 docker compose up 時,它會自動讀取覆蓋。

要在生產環境中使用此 Compose 應用程式,將建立另一個覆蓋檔案,該檔案可能儲存在不同的 git 儲存庫中或由不同的團隊管理。

compose.prod.yml

services:
  web:
    ports:
      - 80:80
    environment:
      PRODUCTION: 'true'

  cache:
    environment:
      TTL: '500'

要使用此生產 Compose 檔案進行部署,您可以執行

$ docker compose -f compose.yml -f compose.prod.yml up -d

這將使用 compose.ymlcompose.prod.yml 中的配置部署所有三個服務,但不會使用 compose.override.yml 中的開發配置。

有關更多資訊,請參閱 在生產環境中使用 Compose

侷限性

Docker Compose 支援為應用程式模型中要包含的許多資源指定相對路徑:服務映象的構建上下文、定義環境變數的檔案位置、繫結掛載卷中使用的本地目錄的路徑。在這樣的約束下,在 monorepo 中的程式碼組織可能變得困難,因為自然的選擇是為每個團隊或元件建立專用資料夾,但這樣一來,Compose 檔案的相對路徑就變得無關緊要了。

參考資訊