Dockerfile中CMD和ENTRYPOINT的用法

一、 ENTRYPOINT指令

ENTRYPOINT 的兩種格式:
• ENTRYPOINT ["executable", "param1", "param2"] (exec格式,推薦使用此格式)
• ENTRYPOINT command param1 param2 (shell 格式)

ENTRYPOINT 的目的和 CMD 一樣,都是指定容器的啓動程序及參數。ENTRYPOINT 在運行時也可以通過 docker run 的參數 --entrypoint 來替代鏡像中默認的ENTRYPOINT,通過 --entrypoint 傳的必須是可執行的二進制程序, 即不會以sh -c 形式執行。

當指定了 ENTRYPOINT (exec格式)後,CMD 的含義就發生了改變,不再是直接運行的命令,而是將 CMD 的內容作爲參數傳給 ENTRYPOINT 指令,換句話說實際執行時,將變爲:<ENTRYPOINT> "<CMD>"

通過docker run <image>啓動容器時的命令行參數將作爲ENTRYPOINT的參數追加到其已有的參數後面,此時所有的CMD參數將無效,被命令行參數覆蓋;

CMD作爲 ENTRYPOINT 的參數時需要是exec格式,如果是shell格式將轉化成/bin/sh -c 式的exec格式,作爲參數傳給 ENTRYPOINT 時可能會出錯;

當指定了ENTRYPOINT 爲shell格式, CMD將無效, 即dockerfile裏的CMD和 啓動容器時傳的命令行參數都將無效,此時ENTRYPOINT 將以 /bin/sh –c 的形式啓動,即作爲sh的子命令來執行,這種形式下ENTRYPOINT的執行程序不能通過Unix 信號控制,因進程號不是容器的PID 1 (sh的進程PID爲1),也就不能以docker stop <container> 的形式來優雅地停止(接收SIGTERM信號)ENTRYPOINT的執行程序 ,因爲這時docker stop <container>會在超時時間後通過發送SIGKILL信號給sh 強制停止容器,這會導致stop時間加長,爲避免這種缺點,在shell命令前加exec,以這種方式運行即可, 如: ENTRYPOINT exec <shell command>。
和shell格式不同,當ENTRYPOINT是exec格式時不會調用shell,通常的shell變量將不會被解析執行,ENTRYPOINT [ "echo", "$HOME" ] 中的$HOME不會被替換,如果需要變量替換,則可以用shell格式的ENTRYPOINT。

二、 CMD指令

啓動容器的時候,需要指定所運行的程序及參數。CMD 指令就是用於指定默認的容器主進程的啓動命令的。

CMD指令有三種格式:
• CMD ["executable","param1","param2"] (exec 格式,推薦用此格式)
• CMD ["param1","param2"] (作爲ENTRYPOINT 的默認參數)
• CMD command param1 param2 (shell 格式)

在dockerfile中只能有1個CMD指令,如有多個,最後一個生效。CMD的目的是提供默認的執行程序或執行程序的參數給容器,如果是參數,需要有ENTRYPOINT提供執行程序。
如果dockerfile中同時指定了ENTRYPOINT和CMD,CMD將作爲ENTRYPOINT的默認參數,這裏兩個指令都指的是exec 格式,都將解析爲JSON數組,所以只能用雙引號;

exec格式不會解析shell環境變量,如CMD [ "echo", "$HOME" ] 將無法解析變量HOME變量,dockerfile裏如果CMD用shell格式,在實際執行時將以 /bin/sh -c 執行,如:
CMD echo $HOME
在實際執行時將變成CMD [ "sh", "-c", "echo $HOME" ] 也就會解析出HOME變量。
CMD用exec格式執行系統的命令時,需要命令的全路徑和JSON數組格式,就是得使用雙引號,每個參數單獨分別地追加在數組中,如下用法:
CMD [“/usr/bin/wc”, ”--help”]

三、 理解和結合使用CMD和ENTRYPOINT

  1. Dockerfile 應該至少指定CMD或ENTRYPOINT其中的1個;
  2. 容器用作可執行的程序應用時應該用ENTRYPOINT;
  3. CMD應該用作ENTRYPOINT的默認參數來使用,或是在容器中執行臨時的命令;
  4. 啓動容器時如果傳遞參數將覆蓋dockerfile中指定的CMD參數;

下表列出了在CMD和ENTRYPOINT結合使用的情況下,哪個命令最終生效:

Dockerfile中CMD和ENTRYPOINT的用法

以上內容參考官方文檔:
https://docs.docker.com/engine/reference/builder/#usage

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章