Dockerfile CMD
在前幾篇的文章中: Docker Certified Associate(DCA)認證考試學習-Dockerfile
在我們查看Docker Run
時,有提到 CMD
與 ENTRYPOINT
並且附上了一個表格
- Dockerfile 最少必須要有一個
CMD
或ENTRYPOINT
指令 - 如果要將container當作成一個可執行檔,使用
ENTRYPOINT
No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT [“exec_entry”, “p1_entry”] | |
---|---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry exec_cmd p1_cmd |
CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
當初只有快速的帶過這部分,並沒有詳細提及
今天來好好將他們的區別研究清楚
首先先看一下CMD的文檔
CMD指令有三種使用格式
CMD ["executable","param1","param2"]
exec格式,優先選擇使用此格式CMD ["param1","param2"]
做為ENTRYPOINT的預設輸入參數CMD command param1 param2
shell格式
並且要注意以下事項
- 一個Dockerfile只能有一個
CMD
指令,如果多於一個的話後面宣告的會蓋掉之前的 - exec格式會將內容解析為JSON Array所以必須使用雙引號不可以是用單引號
- exec格式並不會並不會調用shell
這邊來做幾個簡單測試
#Dockerfile
From alpine
CMD [ "echo", "$HOME" ]
可以對照上方的表格CMD [“exec_cmd”, “p1_cmd”]
and No ENTRYPOINT
,預期輸出的結果為 exec_cmd p1_cmd
因可得知輸出的語法為echo $HOME
這邊因為是使用exec格式所以shell並沒有介入,因此並沒有將$HOME參數修改成我們的地址
$ docker build -t cmdimage .
$ docker run cmdimage
$HOME
如果要使用exec格式還希望調用shell,也是可以做到
#Dockerfile
From alpine
CMD [ "sh", "-c", "echo $HOME" ]
改成這種寫法其實就跟我們平常寫shell命令時一樣
可以對照上方的表格CMD [“exec_cmd”, “p1_cmd”]
and No ENTRYPOINT
,預期輸出的結果為 exec_cmd p1_cmd
因可得知輸出的語法為sh -c "echo $HOME"
$ docker build -t cmdimage .
$ docker run cmdimage
/root
接下來試試看shell格式
#Dockerfile
From alpine
CMD echo $HOME
可以對照上方的表格CMD exec_cmd p1_cmd
and No ENTRYPOINT
,預期輸出的結果為 /bin/sh -c exec_cmd p1_cmd
因可得知輸出的語法為/bin/sh -c echo $HOME
$ docker build -t cmdimage .
$ docker run cmdimage
/root
接下來複習一下docker run的使用方法
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
這邊的[COMMAND]
也就代表Dockerfile 裡面的 CMD
指令,所以在使用docker run如果這邊有帶入參數,那就會覆蓋掉Dockerfile裡的CMD
[node1] (local) root@192.168.0.28 ~/cmd
$ docker run cmdimage echo hello
hello
[node1] (local) root@192.168.0.28 ~/cmd
$ docker run cmdimage && echo hello
/root
hello
Dockerfile ENTRYPOINT
首先先看一下ENTRYPOINT的文檔
ENTRYPOINT指令有兩種使用格式
ENTRYPOINT ["executable", "param1", "param2"]
exec格式,優先選擇使用此格式ENTRYPOINT command param1 param2
shell格式
首先先測試下exec格式
#Dockerfile
From alpine
ENTRYPOINT [ "echo", "$HOME" ]
可以對照上方的表格No CMD
and ENTRYPOINT [“exec_entry”, “p1_entry”]
,預期輸出的結果為 exec_entry p1_entry
$ docker build -t entryimage .
$ docker run entryimage
$HOME
跟CMD一樣如果要使用exec格式還希望調用shell
#Dockerfile
From alpine
ENTRYPOINT [ "sh", "-c", "echo $HOME" ]
$ docker build -t entryimage .
$ docker run entryimage
/root
到目前為止大家應該能看懂表格想要表達的意思了
所以ENTRYPOINT在shell格式下就能很輕鬆的推斷出輸出的結果了
也就是不管有沒有CMD指令ENTRYPOINT在shell格式下只會輸出/bin/sh -c exec_entry p1_entry
也就是說如果Dockerfile要使用同時使用ENTRYPOINT與CMD只能使用shell格式
那麼再做最後的測試
#Dockerfile
From alpine
ENTRYPOINT [ "echo", "$HOME" ]
CMD echo $HOME
可以對照上方的表格CMD exec_cmd p1_cmd
and ENTRYPOINT [“exec_entry”, “p1_entry”]
,預期輸出的結果為 exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd
$ docker build -t entryimage .
$ docker run entryimage
$HOME /bin/sh -c echo $HOME
最後兩個都使用shell格式
#Dockerfile
From alpine
ENTRYPOINT [ "echo", "$HOME" ]
CMD ["echo", "$HOME"]
可以對照上方的表格CMD exec_cmd p1_cmd
and ENTRYPOINT [“exec_entry”, “p1_entry”]
,預期輸出的結果為 exec_entry p1_entry exec_cmd p1_cmd
$ docker build -t entryimage .
$ docker run entryimage
$HOME echo $HOME
那麼如果在docker run 後面在帶參數會發生什麼事呢
[node1] (local) root@192.168.0.28 ~/entry
$ docker run entryimage echo hello
$HOME echo hello
[node1] (local) root@192.168.0.28 ~/entry
$ docker run entryimage && echo hello
$HOME echo $HOME
hello
Summary
今天內容有點雜,不過Docker官方與有說建議使用exec格式,所以真的比較常用的也只有三個
CMD [“exec_cmd”, “p1_cmd”]
+No ENTRYPOINT
=exec_cmd p1_cmd
No CMD
+ENTRYPOINT [“exec_entry”, “p1_entry”]
=exec_entry p1_entry
CMD [“exec_cmd”, “p1_cmd”]
+ENTRYPOINT [“exec_entry”, “p1_entry”]
=exec_entry p1_entry exec_cmd p1_cmd
確實在大多範例也都只會使用到這三種情況,其它情況例如呼叫起程式也同時執行bash的命令,可能才會使用到其他的搭配
可以按照自己的需求來選擇