CMD和ENTRYPOINT的區別


RUN、CMD 和 ENTRYPOINT 這三個 Dockerfile 指令看上去很類似,很容易混淆。本節將通過實踐詳細討論它們的區別。

簡單的說:

  1. RUN 執行命令並創建新的鏡像層,RUN 經常用於安裝軟件包。

  2. CMD 設置容器啟動后默認執行的命令及其參數,但 CMD 能夠被 docker run 后面跟的命令行參數替換。

  3. ENTRYPOINT 配置容器啟動時運行的命令。

下面我們詳細分析。

Shell 和 Exec 格式

我們可用兩種方式指定 RUN、CMD 和 ENTRYPOINT 要運行的命令:Shell 格式和 Exec 格式,二者在使用上有細微的區別。

Shell 格式

<instruction> <command>


例如:

RUN apt-get install python3  

CMD echo "Hello world"  

ENTRYPOINT echo "Hello world" 


當指令執行時,shell 格式底層會調用 /bin/sh -c <command>

例如下面的 Dockerfile 片段:

ENV name Cloud Man  

ENTRYPOINT echo "Hello, $name" 


執行 docker run <image> 將輸出:

Hello, Cloud Man

 

注意環境變量 name 已經被值 Cloud Man 替換。

下面來看 Exec 格式。

Exec 格式

<instruction> ["executable", "param1", "param2", ...]

 

例如:

RUN ["apt-get", "install", "python3"]  

CMD ["/bin/echo", "Hello world"]  

ENTRYPOINT ["/bin/echo", "Hello world"]

 

當指令執行時,會直接調用 <command>,不會被 shell 解析。
例如下面的 Dockerfile 片段:

ENV name Cloud Man  

ENTRYPOINT ["/bin/echo", "Hello, $name"]

 

運行容器將輸出:

Hello, $name

 

注意環境變量“name”沒有被替換。
如果希望使用環境變量,照如下修改

ENV name Cloud Man  

ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]

 

運行容器將輸出:

Hello, Cloud Man

 

CMD 和 ENTRYPOINT 推薦使用 Exec 格式,因為指令可讀性更強,更容易理解。RUN 則兩種格式都可以。

RUN

RUN 指令通常用於安裝應用和軟件包。

RUN 在當前鏡像的頂部執行命令,並通過創建新的鏡像層。Dockerfile 中常常包含多個 RUN 指令。

RUN 有兩種格式:

  1. Shell 格式:RUN

    </li>
    
  2. Exec 格式:RUN ["executable", "param1", "param2"]

    </li>
    

下面是使用 RUN 安裝多個包的例子:

RUN apt-get update && apt-get install -y \  

 bzr \

 cvs \

 git \

 mercurial \

 subversion

 

注意:apt-get update 和 apt-get install 被放在一個 RUN 指令中執行,這樣能夠保證每次安裝的是最新的包。如果 apt-get install 在單獨的 RUN 中執行,則會使用 apt-get update 創建的鏡像層,而這一層可能是很久以前緩存的。

CMD

CMD 指令允許用戶指定容器的默認執行的命令。

此命令會在容器啟動且 docker run 沒有指定其他命令時運行。

  1. 如果 docker run 指定了其他命令,CMD 指定的默認命令將被忽略。

    </li>
    
  2. 如果 Dockerfile 中有多個 CMD 指令,只有最后一個 CMD 有效。

    </li>
    

CMD 有三種格式:

  1. Exec 格式:CMD ["executable","param1","param2"]
    這是 CMD 的推薦格式。

    </li>
    
  2. CMD ["param1","param2"] 為 ENTRYPOINT 提供額外的參數,此時 ENTRYPOINT 必須使用 Exec 格式。

    </li>
    
  3. Shell 格式:CMD command param1 param2

    </li>
    

Exec 和 Shell 格式前面已經介紹過了。
第二種格式 CMD ["param1","param2"] 要與 Exec 格式 的 ENTRYPOINT 指令配合使用,其用途是為 ENTRYPOINT 設置默認的參數。我們將在后面討論 ENTRYPOINT 時舉例說明。

下面看看 CMD 是如何工作的。Dockerfile 片段如下:

CMD echo "Hello world"

 

運行容器 docker run -it [image] 將輸出:

Hello world

 

但當后面加上一個命令,比如 docker run -it [image] /bin/bash,CMD 會被忽略掉,命令 bash 將被執行:

root@10a32dc7d3d3:/#

 

ENTRYPOINT

ENTRYPOINT 指令可讓容器以應用程序或者服務的形式運行。

ENTRYPOINT 看上去與 CMD 很像,它們都可以指定要執行的命令及其參數。不同的地方在於 ENTRYPOINT 不會被忽略,一定會被執行,即使運行 docker run 時指定了其他命令。

ENTRYPOINT 有兩種格式:

  1. Exec 格式:ENTRYPOINT ["executable", "param1", "param2"] 這是 ENTRYPOINT 的推薦格式。

    </li>
    
  2. Shell 格式:ENTRYPOINT command param1 param2

    </li>
    

在為 ENTRYPOINT 選擇格式時必須小心,因為這兩種格式的效果差別很大。

Exec 格式

ENTRYPOINT 的 Exec 格式用於設置要執行的命令及其參數,同時可通過 CMD 提供額外的參數。

ENTRYPOINT 中的參數始終會被使用,而 CMD 的額外參數可以在容器啟動時動態替換掉。

比如下面的 Dockerfile 片段:

ENTRYPOINT ["/bin/echo", "Hello"]  

CMD ["world"]

 

當容器通過 docker run -it [image] 啟動時,輸出為:

Hello world

 

而如果通過 docker run -it [image] CloudMan 啟動,則輸出為:

Hello CloudMan

 

Shell 格式

ENTRYPOINT 的 Shell 格式會忽略任何 CMD 或 docker run 提供的參數。

最佳實踐

  1. 使用 RUN 指令安裝應用和軟件包,構建鏡像。

    </li>
    
  2. 如果 Docker 鏡像的用途是運行應用程序或服務,比如運行一個 MySQL,應該優先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可為 ENTRYPOINT 提供額外的默認參數,同時可利用 docker run 命令行替換默認參數。

    </li>
    
  3. 如果想為容器設置默認的啟動命令,可使用 CMD 指令。用戶可在 docker run 命令行中替換此默認命令。

    </li>
    

到這里,我們已經具備編寫 Dockerfile 的能力了。如果大家還覺得沒把握,推薦一個快速掌握 Dockerfile 的方法:去 Docker Hub 上參考那些官方鏡像的 Dockerfile

好了,我們已經學習完如何創建自己的 image,下一節討論如何分發 image。

二維碼+指紋.png


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM