Dockerfile RUN 、 CMD 、 ENTRYPOINT區別

這些docker指令看起來很類似,容易讓剛開始使用docker的開發人員形成混淆。在這篇文章中,我將解釋CMD、RUN和ENTRYPOINT之間的區別。python

  • RUN 在新圖層中執行命令並建立新圖像。例如,它一般用於安裝軟件包。
  • CMD 設置默認命令和/或參數,當docker容器運行時,能夠從命令行覆蓋這些命令和/或參數。
  • ENTRYPOINT 配置將做爲可執行文件運行的容器。

Docker圖像和圖層

當Docker運行一個容器時,它會在其中運行一個鏡像。此鏡像一般經過執行Docker指令構建,該指令在現有鏡像或OS分佈之上添加層。OS分佈是初始圖像,每一個添加的層都會建立一個新鏡像。git

Shell和Exec形式

全部三個指令(RUN,CMD和ENTRYPOINT)均可以用shell形式或exec形式指定。讓咱們首先熟悉這些形式,由於形式一般比指令自己更容易引發混淆。docker

shell形式

<instruction> <command>
複製代碼

Examples:shell

RUN apt-get install python3
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"
複製代碼

當以shell形式執行指令時,它會調用/bin/sh -c 並進行正常的shell處理。例如,Dockerfile中的如下代碼段bash

ENV name John Dow
ENTRYPOINT echo "Hello, $name"
複製代碼

當容器運行docker run -it 時將輸出ui

Hello, John Dow
複製代碼

注意:變量名稱將替換爲其值。spa

Exec形式

這是CMD和ENTRYPOINT指令的首選形式。命令行

<instruction> ["executable", "param1", "param2", ...]
複製代碼

Examples:版本控制

RUN ["apt-get", "install", "python3"]
CMD ["/bin/echo", "Hello world"]
ENTRYPOINT ["/bin/echo", "Hello world"]
複製代碼

當以exec形式執行指令時,它直接調用可執行文件,而且不會發生shell處理。例如,Dockerfile中的如下代碼段code

ENV name John Dow
ENTRYPOINT ["/bin/echo", "Hello, $name"]
複製代碼

當容器運行docker run -it 時將輸出

Hello, $name
複製代碼

注意:變量名稱未替換。

怎麼運行bash?

若是你須要運行bash(或任何其餘解釋器如sh),使用exec形式與/bin/bash做爲可執行文件。在這種狀況下,將進行正常的shell處理。例如,Dockerfile中的如下代碼段

ENV name John Dow
ENTRYPOINT ["/bin/bash", "-c", "echo Hello, $name"]
複製代碼

當容器運行docker run -it 時將輸出

Hello, John Dow
複製代碼

RUN

RUN指令容許您安裝應用程序和程序包。它在當前鏡像之上執行任何命令,並經過提交結果來建立新層。一般,您會在Dockerfile中找到多個RUN指令。

RUN有兩種形式

  • RUN (shell 形式)
  • RUN ["executable", "param1", "param2"] (exec 形式)

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添加的層,這多是好久之前建立的。建議多個指令用&&隔開在一個run中執行。

CMD

CMD指令容許您設置默認命令,該命令僅在您運行容器不指定命令時候運行。若是Docker容器使用命令運行,則將忽略默認命令。若是Dockerfile具備多個CMD指令,則忽略除最後一個CMD指令以外的全部指令。

CMD有三種形式:

  • CMD ["executable","param1","param2"] (exec 形式, 推薦)
  • CMD ["param1","param2"] (以exec形式爲ENTRYPOINT設置其餘默認參數)
  • CMD command param1 param2 (shell 形式)

第一和第三種形式在Shell和Exec部分進行了解釋。第二種exec形式和ENTRYPOINT指令一塊兒使用。若是容器在沒有命令行參數的狀況下運行,它將設置將在ENTRYPOINT參數以後添加的默認參數。參見ENTRYPOINT。

咱們來看看CMD指令是如何工做的。Dockerfile中的如下片斷

CMD echo "Hello world" 
複製代碼

當容器運行docker run -it 時將輸出

Hello world
複製代碼

可是當容器使用命令運行時,例如, docker run -it /bin/bash,忽略CMD並改成運行bash指令:

root@7de4bed89922:/#
複製代碼

ENTRYPOINT

ENTRYPOINT指令容許您配置將做爲可執行文件運行的容器。它看起來相似於CMD,由於它還容許您使用參數指定命令。區別在於當Docker容器使用命令行參數運行時,ENTRYPOINT命令不會忽略參數。(有一種方法能夠忽略ENTTRYPOINT,但你不太可能這樣作。)

ENTRYPOINT 有兩種形式:

  • ENTRYPOINT ["executable", "param1", "param2"] (exec 形式,推薦)
  • ENTRYPOINT command param1 param2 (shell 形式)

選擇ENTRYPOINT形式時要很是當心,由於不一樣形式執行結果會有很大差別。

Exec 形式

ENTRYPOINT的Exec形式容許您設置命令和參數,而後使用任一形式的CMD來設置更可能更改的其餘參數。使用ENTRYPOINT參數,而能夠經過Docker容器運行時提供的命令行參數覆蓋CMD。例如,Dockerfile中的如下代碼段

ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"]
複製代碼

當容器運行docker run -it 時將輸出

Hello world
複製代碼

可是當容器運行docker run -it John時,將輸出

Hello John
複製代碼

Shell 形式

Shell形式的ENTRYPOINT忽略任何CMD或docker運行命令行參數。

使用RUN指令經過在初始鏡像上添加層來構建鏡像。

在構建可執行的Docker鏡像時,首選ENTRYPOINT的CMD形式。另外若是須要提供額外的默認參數,能夠在docker容器運行時從命令行覆蓋,請使用CMD。

若是須要提供默認命令和/或在docker容器運行時能夠從命令行覆蓋的參數,請選擇CMD。

相關文章
相關標籤/搜索