合併 Compose 檔案

Docker Compose 可讓您合併和覆寫一組 Compose 檔案,以建立複合 Compose 檔案。

根據預設,Compose 會讀取兩個檔案,一個是 compose.yaml,另一個是選擇性的 compose.override.yaml 檔案。按照慣例,compose.yaml 包含您的基本設定。覆寫檔案可以包含現有服務的設定覆寫或全新的服務。

如果服務在兩個檔案中都有定義,Compose 會使用下方和 Compose 規格 中描述的規則來合併設定。

如何合併多個 Compose 檔案

若要使用多個覆寫檔案,或使用不同名稱的覆寫檔案,您可以使用預先定義的 COMPOSE_FILE 環境變數,或使用 -f 選項來指定檔案清單。

Compose 會按照在命令列中指定的順序合併檔案。後續檔案可能會合併、覆寫或新增到其前一個檔案。

例如

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

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

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

compose.admin.yaml 也可能會指定相同的服務

webapp:
  environment:
    - DEBUG=1

任何相符的欄位都會覆寫先前的檔案。新的值會新增至 webapp 服務設定

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

合併規則

  • 路徑是相對於基本檔案進行評估的。當您使用多個 Compose 檔案時,您必須確保檔案中的所有路徑都相對於基本 Compose 檔案(使用 -f 指定的第一個 Compose 檔案)。這是必要的,因為覆寫檔案不需要是有效的 Compose 檔案。覆寫檔案可以包含小的設定片段。追蹤服務的哪個片段相對於哪個路徑既困難又令人困惑,因此為了讓路徑更容易理解,所有路徑都必須相對於基本檔案定義。

    提示

    您可以使用 docker compose config 來檢查您的合併設定,並避免與路徑相關的問題。

  • 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 規格中的 合併和覆寫

額外資訊

  • 使用 -f 是選擇性的。如果未提供,Compose 會在工作目錄及其父目錄中搜尋 compose.yamlcompose.override.yaml 檔案。您必須至少提供 compose.yaml 檔案。如果兩個檔案都存在於相同的目錄層級,Compose 會將它們組合成單一設定。

  • 您可以將 -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.yaml 檔案。您可以使用像 docker compose pull 這樣的指令,透過使用 -f 旗標,從任何地方取得 db 服務的 postgres 映像檔,如下所示:docker compose -f ~/sandbox/rails/compose.yaml pull db

    以下是完整的範例

    $ docker compose -f ~/sandbox/rails/compose.yaml 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 應用程式更改為類生產環境(可能是生產環境、預備環境或 CI)。為了支援這些差異,您可以將 Compose 設定拆分到幾個不同的檔案中。

從定義服務標準設定的基本檔案開始。

compose.yaml

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

  db:
    image: postgres:latest

  cache:
    image: redis:latest

在此範例中,開發設定將一些埠公開給主機,將我們的程式碼掛載為磁碟區,並建置 web 映像檔。

compose.override.yaml

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.yaml

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

  cache:
    environment:
      TTL: '500'

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

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

這將使用 compose.yamlcompose.prod.yaml 中的設定部署所有三個服務,但不使用 compose.override.yaml 中的開發設定。

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

限制

Docker Compose 支援應用程式模型中包含的許多資源的相對路徑:服務映像檔的建置上下文、定義環境變數的檔案位置、繫結掛載磁碟區中使用的本機目錄的路徑。由於這種限制,在單體儲存庫中的程式碼組織可能會變得困難,因為自然的選擇是每個團隊或元件都有專用的資料夾,但 Compose 檔案的相對路徑就會變得不相關。

參考資訊