Docker Certified Associate(DCA)認證考試學習- ARG and ENV Docker Certified Associate(DCA)認證相關資源、ARG、ENV

Published on Thursday, February 16, 2023

Dockerfile ENV

今天要來學習 ENV 的使用方法
照慣例先看一下ENV文檔

格式呢只需要 ENV 開頭在搭配一個key value值即可,並且需要有value並不能為空

ENV <key>=<value> ...

先來做幾個測試

#Dockerfile
From alpine
ENV version=1.0.0
RUN echo $version
CMD echo $version
docker build -t versiontest .
docker run versiontest
[node1] (local) root@192.168.0.13 ~
$ docker build -t versiontest .

...

Step 3/4 : RUN echo $version
 ---> Running in 91e6c372f426
1.0.0

...

這邊當Docker看到Dockerfile裡面有宣告ENV會將此key value保存到image裡面,這樣才能保證在所有執行階段都讀取到同一個值
可以使用docker inspect來檢查,就能看到我們的version環境變數被包在image之中

[node1] (local) root@192.168.0.13 ~/hello
$ docker inspect versiontest

...

"ContainerConfig": {
            "Hostname": "b75725f395b0",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "version=1.0.0"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"/bin/sh\" \"-c\" \"echo $version\"]"
            ],
            "Image": "sha256:5c5ab36f7d2e057f0f2a233760b03918eb7154769517cab82fd14f6c7cd7da6f",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },

...

也可以在Docker run期間將環境變數做修改

docker run --env version=1.0.1 versiontest
1.0.1

但是需要特別注意此環境變數會附蓋掉container內部的環境變數,因此如果有重名需要特別小心 例如Home變數

#Dockerfile
From alpine
ENV HOME=/usr
RUN echo $HOME

到container內部後確實原本預設的HOME被修改成我們自定義的值了

docker build -t versiontest .
docker run -dit versiontest

[node1] (local) root@192.168.0.13 ~/hello
$ docker attach c68
/ # env
HOSTNAME=c6808dc07543
SHLVL=1
HOME=/usr
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/

Dockerfile ARG

接下來是ARG的使用方法
先看一下ARG文檔

格式也只需要ARG開頭在搭配一個key value的值即可,但是Value不是必填,如果為空需要在運行docker run時提供參數

ARG <name>[=<default value>]
#Dockerfile
From alpine
ARG version=1.0.0
RUN echo $version
CMD echo $version
docker build -t versiontest .

這邊第三步驟會去抓ARG的值並輸出1.0.0

[node1] (local) root@192.168.0.13 ~/hello
$ docker build -t versiontest .

...

Step 3/4 : RUN echo $version
 ---> Running in d1291bdd0b33
1.0.0
Removing intermediate container d1291bdd0b33
 ---> 2f16517f0b6b

...

這邊run 起來之後並沒有輸出任何值,因為並沒有宣告$version這個環境變數所以會輸出空值

[node1] (local) root@192.168.0.13 ~/hello
$ docker run versiontest

#Dockerfile
From alpine
ARG version=1.0.0
ENV version=2.0.0
RUN echo $version
CMD echo $version

如果ARG與ENV名稱一樣則,ENV的優先度最高會附蓋掉ARG

[node1] (local) root@192.168.0.13 ~/hello
$ docker build -t versiontest . --no-cache --build-arg version=3.0.0

...

Step 4/5 : RUN echo $version
 ---> Running in c2c92651638d
2.0.0
Removing intermediate container c2c92651638d
 ---> 8c9430d36eaa

...

兩者也可以做搭配可以達到預設值得效果

From alpine
ARG version
ENV version=${version:-2.0.0}
RUN echo $version
CMD echo $version

這樣可以做到如果有帶參數就使用參數的值,沒有帶的話就使用:-後面的當作預設值

[node1] (local) root@192.168.0.13 ~/hello
$ docker build -t versiontest . --no-cache

...

Step 4/5 : RUN echo $version
 ---> Running in f0c3972a1567
2.0.0
Removing intermediate container f0c3972a1567
 ---> 5b76b7cb3fd0

...

這個:-的語法稱為Environment replacement
要使用此語法需要使用大括號將變數包起來,並且有兩種格式

  • $ 如果有帶參數就使用參數的值,沒有帶的話就使用:-後面的值當作預設值
  • ${version:+2.0.0} 如果有帶參數就使用:+後面的值當作預設值(並不會使用你所輸入的值),沒有帶的話就使用就輸出空值,類似有輸出就ON沒輸出就OFF
From alpine
ARG version
ENV version=${version:+2.0.0}
RUN echo $version
CMD echo $version
[node1] (local) root@192.168.0.13 ~/hello
$ docker build -t versiontest . --no-cache

...

Step 4/5 : RUN echo $version
 ---> Running in 77fa749b6940

Removing intermediate container 77fa749b6940
 ---> 03635aa4b444
 
...

[node1] (local) root@192.168.0.13 ~/hello
$ docker build -t versiontest . --no-cache --build-arg version=3.0.0

...

Step 4/5 : RUN echo $version
 ---> Running in d16612af788a
2.0.0
Removing intermediate container d16612af788a
 ---> c76344209a6c
 
...


Summary

以上就是ENV和ARG的基礎用法,ARG只會在build期間才會使用,ENV則是會一直跟著image
兩個都有自己使用的場景,例如可以將選擇image版本的參數設定在ARG這樣就可以在docker run時動態選擇自己需要的版本
ENV則是會影響到container內的環境變數,所以可以用來指定目前是Debug或是Prod環境,方便給我們內部運行的程式做判別