Docker 中的 RUN、CMD 和 Entrypoint


RUN、CMD 和 Entrypoint 命令通常讓 Docker 開發者感到困惑。理解這三個命令的概念將有助於更清晰地理解它們。

當我們嘗試使用 Dockerfile 構建映象時,指令會一步一步地執行。第一個指令通常是拉取一個基礎映象,例如 Ubuntu、CentOS 等作業系統發行版。之後,我們可以透過使用 FROM 和 AS 命令包含更多映象或修改映象來修改基礎映象。每個這樣的指令都會建立一個新的中間映象構建,併為每個構建建立快取。最終的 Docker 映象可以被認為是一個分層結構,其中有一個核心或基礎映象,在其之上有幾個分層的中間映象。

為了深入理解這三個命令,我們首先需要了解 shell 形式和 exec 形式。

可執行形式 (exec form)

此形式通常用於 Entrypoint 和 CMD 命令。其形式為:

<instruction> [“executable”, “parameter”, “parameter”, ….]

當我們以這種形式執行指令時,不會進行 shell 處理,而是直接呼叫可執行檔案。

考慮以下命令。

RUN [“apt-get”, “install”, “vim”]
ENTRYPOINT [“/bin/echo”, “TutorialsPoint”]
CMD [“/bin/echo”, “TutorialsPoint”]

如果我們用以下指令編寫 Dockerfile:

ENV variable TutorialsPoint
ENTRYPOINT [“/bin/echo”, “$variable”]

當我們嘗試執行映象時,會生成以下輸出。

$variable

Shell 形式

當我們使用 shell 形式執行指令時,會進行正常的 shell 處理。它在幕後呼叫命令 `/bin/sh -c {command}`。

其形式為:`<你的指令> <命令>`

考慮以下命令。

RUN apt-get -y update
CMD echo “TutorialsPoint”
ENTRYPOINT echo “TutorialsPoint”

以下 Dockerfile:

ENV variable TutorialsPoint
ENTRYPOINT echo “$variable”

將輸出:

TutorialsPoint

現在我們已經深入瞭解了這兩種形式,讓我們繼續討論這三個命令。

RUN

RUN 命令始終在新層中執行。它允許你在現有映象層之上安裝軟體包和應用程式,並在其之上建立一個新層。

它可以用 shell 形式和 exec 形式編寫。示例包括:

RUN apt-get -y update (shell form)
RUN [“apt-get”, “install”, “vim”] (exec form)

CMD

使用 CMD 命令,你可以設定預設命令。如果你執行特定容器時沒有指定任何命令,則會執行此命令。如果你在執行 Docker 容器時指定了命令,則會忽略預設命令。請注意,如果在 Dockerfile 中指定了多個 CMD 指令,則只會執行最後一個。

以下是執行 CMD 命令的不同方法。

  • CMD `<命令>` 引數1,引數2…… (Shell 形式)

  • CMD [`可執行命令`,“引數1”,“引數2”,……] (可執行形式)

  • CMD [`引數1`,“引數2”]

第三種方法用於設定一些額外的預設引數,當你在可執行形式中使用 ENTRYPOINT 並執行容器時沒有在命令列中指定任何引數時,這些引數將插入到預設引數之後。

考慮 Dockerfile 中的以下命令。

CMD echo “TutorialsPoint”

如果你在不指定引數的情況下執行它 (docker run -it image_name),輸出將是:

TutorialsPoint

如果你透過指定 CLI 引數執行它 (docker run -it image_name /bin/bash),它將簡單地開啟一個 bash shell。

ENTRYPOINT

它看起來類似於 CMD 命令。但是,不同之處在於,當使用 CLI 引數執行容器時,它不會忽略引數。ENTRYPOINT 命令的兩種形式為:

  • ENTRYPOINT `<命令>` 引數1,引數2…… (Shell 形式)

  • ENTRYPOINT [`可執行命令`,“引數1”,“引數2”,……] (可執行形式)

當使用 ENTRYPOINT 命令的可執行形式時,它允許你使用 CMD 命令設定附加引數。如果以 shell 形式使用它,它將忽略 CMD 引數或任何 CLI 引數。

考慮以下示例。

ENTRYPOINT [“/bin/echo”, “TutorialsPoint”]
CMD [“Docker”]
  • 如果你嘗試在不指定任何 CLI 引數的情況下執行容器 (docker run -it image_name),輸出將是:TutorialsPoint Docker

  • 如果你指定 CLI 引數 (docker run -it image_name DockerTutorials),輸出將是:TutorialsPoint DockerTutorials。

總而言之,如果你想指定預設引數並希望在指定 CLI 引數時將其覆蓋,請使用 CMD 命令。如果你想執行容器並確保始終執行特定命令,請使用 ENTRYPOINT。RUN 只是用於在基礎映象之上構建附加映象層。

更新於:2020年10月1日

5K+ 瀏覽量

開啟你的職業生涯

完成課程獲得認證

開始學習
廣告