CMD與ENTRYPOINT都可以代表容器的啟動命令,單叢語義上來理解,CMD是一個命令或者口令,而ENTRYPOINT則是一個入口(相當於容器啟動時的入口),那麼其實就可以理解為每當我們開啟一個容器都需要帶著口令去進入容器的入口。雖然兩者可以單獨使用,但根據業務需求往往是將兩者搭配起來使用更加方便與規範。
先來看一張表
這是在Dockerfile中使用CMD與ENTRYPOINT的幾種組合情況,兩者可以定義在執行容器時執行了什麼命令。
注意事項:
- CMD與ENTRYPOINT在Dockerfile裡應該至少指定一個
- 當容器作為可執行檔案使用時,應該定義ENTRYPOINT
- CMD應該用作定義ENTRYPOINT命令或在容器中執行特別命令的預設引數的方法
- 當執行帶有替代引數的容器時,CMD將被覆蓋
兩者單獨使用
從表中可以看出兩者均可單獨當做啟動命令使用,但是靈活性並不是很高,比如傳參等。
1. 對於CMD來講,有三種寫法:
- CMD ["executable","p1","p2"] (exec方式, 首選方式)
- CMD ["p1","p2"] (為ENTRYPOINT提供預設引數,需與ENTRYPOINT結合使用)
- CMD command p1 p2 (shell形式)
當在Dockerfile中單獨使用CMD作為容器啟動命令(CMD ["executable","p1","p2"] )時,只允許使用一個CMD,若有多個則以最後一個為主。
此外,CMD作為啟動命令,當外部(命令列)傳入啟動命令時,外部命令會覆蓋CMD中的啟動命令。
2. 對於ENTRYPOINT來講,有兩種寫法:
- ENTRYPOINT ["executable", "p1", "p2"] (exec方式, 首選方式)
- ENTRYPOINT command p1 p2 (shell 形式)
當在Dockerfile中單獨使用ENTRYPOINT作為容器啟動命令時,外部傳入的啟動命令不會覆蓋ENTRYPOINT中的命令。
另外需要注意的是兩者通過exec的方式取不出來環境變數,但是通過shell方式可以取出環境變數。
如果既想要使用exec方式又要取環境變數,則可以通過/bin/sh -c的方式(RUN指令也類似)
例如:ENTRYPOINT ["/bin/sh", "-c", "echo ${p1}"] (["/bin/sh", "-c", "指令均寫在這裡"] = shell形式)
兩者結合使用
官方推薦:ENTRYPOINT(提供可執行命令+引數(可選)) + CMD(只提供引數) = 容器的完整命令
如果使用CMD為ENTRYPOINT指令提供預設引數,則CMD和ENTRYPOINT指令均應使用JSON陣列格式指定。
在CMD中自定義的引數必須要傳完整,容器才可成功啟動。