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環境,方便給我們內部運行的程式做判別