使用插值在 Compose 檔案中設定、使用和管理變數

Compose 檔案可以使用變數來提供更大的靈活性。如果您想要快速地在映象標籤之間切換以測試多個版本,或者想要調整卷源以適應您的本地環境,則無需每次都編輯 Compose 檔案,只需設定在執行時將值插入 Compose 檔案的變數即可。

插值還可以用於在執行時將值插入 Compose 檔案中,然後用於將變數傳遞到容器的環境中

以下是一個簡單的示例

$ cat .env
TAG=v1.5
$ cat compose.yml
services:
  web:
    image: "webapp:${TAG}"

當您執行 docker compose up 時,Compose 檔案中定義的 web 服務將在 .env 檔案中設定的 webapp:v1.5 映象中進行 插值。您可以使用 config 命令 來驗證這一點,該命令會將已解析的應用程式配置列印到終端

$ docker compose config
services:
  web:
    image: 'webapp:v1.5'

插值語法

插值適用於未加引號和雙引號的值。支援帶大括號 (${VAR}) 和不帶大括號 ($VAR) 的表示式。

對於帶大括號的表示式,支援以下格式

  • 直接替換
    • ${VAR} -> VAR 的值
  • 預設值
    • ${VAR:-default} -> 如果 VAR 已設定且不為空,則為 VAR 的值,否則為 default
    • ${VAR-default} -> 如果 VAR 已設定,則為 VAR 的值,否則為 default
  • 必需值
    • ${VAR:?error} -> 如果 VAR 已設定且不為空,則為 VAR 的值,否則退出並顯示錯誤
    • ${VAR?error} -> 如果 VAR 已設定,則為 VAR 的值,否則退出並顯示錯誤
  • 替代值
    • ${VAR:+replacement} -> 如果 VAR 已設定且不為空,則為 replacement,否則為空
    • ${VAR+replacement} -> 如果 VAR 已設定,則為 replacement,否則為空

有關詳細資訊,請參閱 Compose 規範中的 插值

使用插值設定變數的方法

Docker Compose 可以從多個來源將變數插值到您的 Compose 檔案中。

請注意,當多個來源聲明瞭相同的變數時,會應用優先順序

  1. 來自 shell 環境的變數
  2. 如果未設定 --env-file,則為本地工作目錄 (PWD) 中的 .env 檔案設定的變數
  3. --env-file 設定的檔案或專案目錄中的 .env 檔案設定的變數

您可以透過執行 docker compose config --environment 來檢視 Compose 用於插值 Compose 模型的變數和值。

.env 檔案

Docker Compose 中的 .env 檔案是一個文字檔案,用於定義在執行 docker compose up 時應提供用於插值的變數。此檔案通常包含變數的鍵值對,它允許您在一個位置集中和管理配置。如果您需要儲存多個變數,則 .env 檔案非常有用。

.env 檔案是設定變數的預設方法。.env 檔案應放置在專案目錄的根目錄中,與您的 compose.yaml 檔案並排。有關格式化環境檔案的更多資訊,請參閱 環境檔案語法

基本示例

$ cat .env
## define COMPOSE_DEBUG based on DEV_MODE, defaults to false
COMPOSE_DEBUG=${DEV_MODE:-false}

$ cat compose.yaml 
  services:
    webapp:
      image: my-webapp-image
      environment:
        - DEBUG=${COMPOSE_DEBUG}

$ DEV_MODE=true docker compose config
services:
  webapp:
    environment:
      DEBUG: "true"

其他資訊

  • 如果您在 .env 檔案中定義了一個變數,則可以使用 environment 屬性compose.yml 中直接引用它。例如,如果您的 .env 檔案包含環境變數 DEBUG=1,並且您的 compose.yml 檔案如下所示

     services:
       webapp:
         image: my-webapp-image
         environment:
           - DEBUG=${DEBUG}

    Docker Compose 會將 ${DEBUG} 替換為 .env 檔案中的值

    重要事項

    請注意,當在 .env 檔案中使用變數時,請注意 環境變數優先順序,這些變數作為容器環境中的環境變數。

  • 您可以將 .env 檔案放置在專案目錄根目錄以外的位置,然後使用 CLI 中的 --env-file 選項,以便 Compose 可以導航到它。

  • 如果 使用 --env-file 替換,則 .env 檔案可以被另一個 .env 覆蓋。

重要事項

.env 檔案進行替換是 Docker Compose CLI 的一項功能。

在執行 docker stack deploy 時,Swarm 不支援它。

.env 檔案語法

以下語法規則適用於環境檔案

  • # 開頭的行將被視為註釋並被忽略。
  • 空白行將被忽略。
  • 未加引號和雙引號 (") 的值將應用插值。
  • 每行表示一個鍵值對。值可以可選地用引號引起來。
    • VAR=VAL -> VAL
    • VAR="VAL" -> VAL
    • VAR='VAL' -> VAL
  • 未加引號值的內聯註釋必須以空格開頭。
    • VAR=VAL # comment -> VAL
    • VAR=VAL# not a comment -> VAL# not a comment
  • 帶引號值的內聯註釋必須緊跟在結束引號之後。
    • VAR="VAL # not a comment" -> VAL # not a comment
    • VAR="VAL" # comment -> VAL
  • 單引號 (') 值將按字面意思使用。
    • VAR='$OTHER' -> $OTHER
    • VAR='${OTHER}' -> ${OTHER}
  • 可以使用 \ 對引號進行轉義。
    • VAR='Let\'s go!' -> Let's go!
    • VAR="{\"hello\": \"json\"}" -> {"hello": "json"}
  • 在雙引號值中支援常見的 shell 轉義序列,包括 \n\r\t\\
    • VAR="some\tvalue" -> some value
    • VAR='some\tvalue' -> some\tvalue
    • VAR=some\tvalue -> some\tvalue

使用 --env-file 替換

您可以在 .env 檔案中設定多個環境變數的預設值,然後將該檔案作為引數傳遞給 CLI。

這種方法的優點是您可以將檔案儲存在任何位置並適當地命名它,例如,此檔案路徑相對於執行 Docker Compose 命令的當前工作目錄。透過 --env-file 選項傳遞檔案路徑

$ docker compose --env-file ./config/.env.dev up

其他資訊

  • 如果您想要臨時覆蓋 compose.yml 檔案中已引用的 .env 檔案,則此方法非常有用。例如,您可能對生產 (.env.prod) 和測試 (.env.test) 有不同的 .env 檔案。在以下示例中,有兩個環境檔案,.env.env.dev。兩者都為 TAG 設定了不同的值。
    $ cat .env
    TAG=v1.5
    $ cat ./config/.env.dev
    TAG=v1.6
    $ cat compose.yml
    services:
      web:
        image: "webapp:${TAG}"
    
    如果命令列中未使用 --env-file,則會預設載入 .env 檔案
    $ docker compose config
    services:
      web:
        image: 'webapp:v1.5'
    
    傳遞 --env-file 引數將覆蓋預設檔案路徑
    $ docker compose --env-file ./config/.env.dev config
    services:
      web:
        image: 'webapp:v1.6'
    
    當傳遞無效的檔案路徑作為 --env-file 引數時,Compose 會返回錯誤
    $ docker compose --env-file ./doesnotexist/.env.dev  config
    ERROR: Couldn't find env file: /home/user/./doesnotexist/.env.dev
    
  • 您可以使用多個 --env-file 選項來指定多個環境檔案,Docker Compose 會按順序讀取它們。後面的檔案可以覆蓋前面的檔案中的變數。
    $ docker compose --env-file .env --env-file .env.override up
    
  • 您可以在啟動容器時從命令列覆蓋特定的環境變數。
    $ docker compose --env-file .env.dev up -e DATABASE_URL=mysql://new_user:new_password@new_db:3306/new_database
    

本地 .env 檔案與.env 檔案

.env 檔案還可以用於宣告 預定義的環境變數,這些變數用於控制 Compose 行為和要載入的檔案。

在沒有顯式 --env-file 標誌的情況下執行時,Compose 會在您的工作目錄 ( PWD) 中搜索 .env 檔案,並載入自配置和插值的變數。如果此檔案中的值定義了 COMPOSE_FILE 預定義變數,這會導致專案目錄設定為另一個資料夾,Compose 會載入第二個 .env 檔案(如果存在)。第二個 .env 檔案的優先順序較低。

此機制允許使用自定義變數集作為覆蓋來呼叫現有 Compose 專案,而無需透過命令列傳遞環境變數。

$ cat .env
COMPOSE_FILE=../compose.yaml
POSTGRES_VERSION=9.3

$ cat ../compose.yaml 
services:
  db:
    image: "postgres:${POSTGRES_VERSION}"
$ cat ../.env
POSTGRES_VERSION=9.2

$ docker compose config
services:
  db:
    image: "postgres:9.3"

從 shell 替換

您可以使用主機上的現有環境變數或執行 docker compose 命令的 shell 環境中的環境變數。這使您能夠在執行時將值動態注入到 Docker Compose 配置中。例如,假設 shell 包含 POSTGRES_VERSION=9.3,並且您提供以下配置

db:
  image: "postgres:${POSTGRES_VERSION}"

當您使用此配置執行 docker compose up 時,Compose 會在 shell 中查詢 POSTGRES_VERSION 環境變數,並將它的值替換進去。對於此示例,Compose 會在執行配置之前將映象解析為 postgres:9.3

如果環境變數未設定,Compose 會用空字串替換。在前面的示例中,如果未設定 POSTGRES_VERSION,則 image 選項的值為 postgres:

注意

postgres: 不是有效的映象引用。Docker 期望引用沒有標籤,例如 postgres,預設為最新映象,或者帶有標籤,例如 postgres:15