環境變數(Environment variable)是開發時常見用來控制程式行為的方法之一。

近年隨著 Docker 被普遍運用在開發環境之中,如何方便地在 Docker 中使用環境變數就變成必學的課題之一。

本篇介紹幾種 Docker 與 Docker compose 中設定環境變數的方法。

本文環境

  • Docker 19.03

Dockefile

第 1 種,利用指令將環境變數傳進去 Docker container ,例如以下指令:

$ docker run -e KEY=VALUE <container>

範例:

$ docker run -e DEBUG=1 -e TEST=1 <container>

p.s. 多個變數的情況就得使用多個 -e 參數

第 2 種,在 Dockerfile 中設定 ENV :

例如以下 Dockerfile

FROM busybox
ENV DEBUG=1
ENV TEST=1
CMD ["env"]

上述 Dockerfile 可以使用以下指令建置:

$ docker build --tag printenv .

接著,用以下指令執行 docker container ,看看是否有設定成功:

$ docker run printenv

成功的話,可以看到以下執行結果:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=3f3704db126f
DEBUG=1
TEST=1
HOME=/root

除了實際執行之外,也可以用 docker inspect 指令查看 ENV 的設定:

$ docker inspect printenv --format='{{.ContainerConfig.Env}}'

以下為執行結果(可以看到我們設定的環境變數):

[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin DEBUG=1 TEST=1]

或者直接用以下指令,查看 Env 的部分:

$ docker inspect printenv

執行結果:

...(略)...
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "DEBUG=1",
                "TEST=1"
            ],
...(略)...

Docker-compose

第 1 種,在 Docker compose file 中直接使用 ${環境變數名稱} ,執行 docker-compose 指令時會自動被代入。

例如:

$ export TAG=1.0

以下是 docker-compose.yml 的範例,當我們執行 docker-compose up 時, ${TAG} 會自動被代換成環境變數 TAG 的值,也就是 1.0 ,最後變成 webapp:1.0

web:
  image: "webapp:${TAG}"

第 2 種則是在 Docker compose file 中設定 environment ,例如以下 docker-compose.yml 範例:

web:
  image: "webapp"
  environment:
    - DEBUG=1
      - TEST=1

第 3 種, .env 檔案。

在存放 docker-compose.yml 檔案的資料夾底下新增 .env 檔案, docker-compose 指令執行時也會自動將其中的環境變數帶入。

例如以下資料夾中有 3 個檔案:

.
├── .env
├── Dockerfile
└── docker-compose.yml

以下為 3 個範例檔案的內容。

Dockerfile 檔案內容:

FROM busybox
CMD ["env"]

.env 檔案內容:

TAG=1.0
DEBUG=0
TEST=1

docker-compose.yml 檔案內容:

version: "3"
services:
  machine:
    build: .
    environment:
      - DEBUG=${DEBUG}
      - TEST=${TEST}

接著,執行以下指令,看看結果:

$ docker-compose up

執行成功的話,將可以看到環境變數被順利傳進 container 內:

Starting t_machine_1 ... done
Attaching to t_machine_1
machine_1  | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
machine_1  | HOSTNAME=a8287d65d347
machine_1  | DEBUG=0
machine_1  | TEST=1
machine_1  | HOME=/root
t_machine_1 exited with code 0

此外,可以注意到 .env 作用範圍只作用於 docker-compose.ymlTAG=1.0 並沒有傳進 container 中,如果要將 .env 中的環境變數也傳進 container 中,就必須明確在 enviroment 中設定。

除了預設的 .env 之外, 也可以設定 env_file 載入指定的 env 設定檔:

version: "3"
services:
  machine:
    build: .
    env_file:
      - machine.env
    environment:
      - DEBUG=${DEBUG}
      - TEST=${TEST}

環境變數的優先權

由於有多種載入環境變數的方式,所以這些方式之間也是有優先權的,以下次序是由官方文件提供:

  1. Compose file
  2. Shell environment variables
  3. Environment file
  4. Dockerfile

越前面的項目,其優先權較大,例如同時在 docker-compose.ymlDockerfile 中都設定相同的環境變數時,最後會以 docker-compose.yml 中的設定為準。

References

Environment variables in Compose | Docker Documentation