【docker】CMD ENTRYPOINT 區別 終極解讀!

轉載於:https://blog.csdn.net/u010900754/article/details/78526443

昨天用Dockerfile來啓動mongodb的集羣,啓動參數--replSet死活沒執行,最後就決定研究一哈cmd和entrypoint。但是上網看了一些資料個人覺得講的不好,還是沒有說出根本的東西,決定自己研究並且整理一哈。

首先上docker官網:https://docs.docker.com/engine/reference/builder/#cmd

感覺官網關於這兩個命令講的簡直不要太清楚。


cmd:

這個命令是用來做什麼的?下面是官網的答案:

[html] view plain copy
  1. The main purpose of a CMD is to provide defaults for an executing container. These defaults can include an executable, or they can omit the executable, in which case you must specify an ENTRYPOINT instruction as well.  
意思是,cmd給出的是一個容器的默認的可執行體。也就是容器啓動以後,默認的執行的命令。重點就是這個“默認”。意味着,如果docker run沒有指定任何的執行命令或者dockerfile裏面也沒有entrypoint,那麼,就會使用cmd指定的默認的執行命令執行。同時也從側面說明了entrypoint的含義,它纔是真正的容器啓動以後要執行命令。

所以這句話就給出了cmd命令的一個角色定位,它主要作用是默認的容器啓動執行命令。(注意不是“全部”作用)

這也是爲什麼大多數網上博客論壇說的“cmd會被覆蓋”,其實爲什麼會覆蓋?因爲cmd的角色定位就是默認,如果你不額外指定,那麼就執行cmd的命令,否則呢?只要你指定了,那麼就不會執行cmd,也就是cmd會被覆蓋。

明白了cmd命令的主要用途。下面就看看具體用法。

總共有三種用法:

[html] view plain copy
  1. The CMD instruction has three forms:  
  2.   
  3. CMD ["executable","param1","param2"] (exec form, this is the preferred form)  
  4. CMD ["param1","param2"] (as default parameters to ENTRYPOINT)  
  5. CMD command param1 param2 (shell form)  

因爲還沒有講entrypoint,所以先不看用法2。

用法3:shell form,即沒有中括號的形式。那麼命令command默認是在“/bin/sh -c”下執行的。比如下面的dockerfile:

[html] view plain copy
  1. FROM centos  
  2.   
  3. CMD echo "hello cmd!"  
運行:


用法1:帶有中括號的形式。這時,命令沒有再任何shell終端環境下,如果我們要執行shell,必須把shell加入到中括號的參數中。這種用法就像一個c語言的exec函數,意思是我們要執行一個進程。如果採用非shell的方法,那麼上面的例子要修改爲:

[html] view plain copy
  1. FROM centos  
  2.   
  3. CMD ["/bin/bash", "-c", "echo 'hello cmd!'"]  
需要注意,採用中括號形式,那麼第一個參數必須是命令的全路徑才行。而且,一個dockerfile至多只能有一個cmd,如果有多個,只有最後一個生效。

官網推薦採用這種方法。

當然,以上都是體現了cmd的“默認”行爲。如果我們在run時指定了命令或者有entrypoint,那麼cmd就會被覆蓋。仍然是上面的image。run命令變了:



可以看到,最終容器裏面執行的是run命令後面的命令,而不是cmd裏面定義的。


接下來再看entrypoint:

[html] view plain copy
  1. An ENTRYPOINT allows you to configure a container that will run as an executable.  
也就是說entrypoint纔是正統地用於定義容器啓動以後的執行體的,其實我們從名字也可以理解,這個是容器的“入口”。

有兩種用法:

[html] view plain copy
  1. ENTRYPOINT has two forms:  
  2.   
  3. ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)  
  4. ENTRYPOINT command param1 param2 (shell form)  

命令行和shell。

先看命令行模式,也就是帶中括號的。和cmd的中括號形式是一致的,但是這裏貌似是在shell的環境下執行的,與cmd有區別。如果run命令後面有東西,那麼後面的全部都會作爲entrypoint的參數。如果run後面沒有額外的東西,但是cmd有,那麼cmd的全部內容會作爲entrypoint的參數,這同時是cmd的第二種用法。這也是網上說的entrypoint不會被覆蓋。當然如果要在run裏面覆蓋,也是有辦法的,使用--entrypoint即可。

下面看幾個例子。

dockerfile爲:

[html] view plain copy
  1. FROM centos  
  2.   
  3. CMD ["p in cmd"]  
  4. ENTRYPOINT ["echo"]  
如果run不帶參數:


如果run帶參數:


而且,確實entrypoint的中括號形式下,command是在shell環境下運行的,否則這裏的echo是無法被執行的。

第二種是shell模式的。在這種模式下,任何run和cmd的參數都無法被傳入到entrypoint裏。官網推薦第一種用法。

[html] view plain copy
  1. FROM centos  
  2.   
  3. CMD ["p in cmd"]  
  4. ENTRYPOINT echo  


cmd的參數沒有被打印。


總結下一般該怎麼使用:一般還是會用entrypoint的中括號形式作爲docker 容器啓動以後的默認執行命令,裏面放的是不變的部分,可變部分比如命令參數可以使用cmd的形式提供默認版本,也就是run裏面沒有任何參數時使用的默認參數。如果我們想用默認參數,就直接run,否則想用其他參數,就run 裏面加參數。


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