簡體   English   中英

Dockerfile 中 RUN 和 CMD 的區別

[英]Difference between RUN and CMD in a Dockerfile

我對什么時候應該使用CMDRUN感到困惑。 例如,要執行 bash/shell 命令(即ls -la ),我將始終使用CMD或者是否存在使用RUN 試圖了解關於這兩個類似Dockerfile指令的最佳實踐。

RUN是一個鏡像構建步驟, RUN命令后容器的狀態將被提交到容器鏡像。 一個 Dockerfile 可以有許多RUN步驟,這些步驟相互疊加以構建映像。

CMD是當您啟動構建的鏡像時容器默認執行的命令。 Dockerfile 將只使用最終定義的CMD 使用docker run $image $other_command啟動容器時,可以覆蓋CMD

ENTRYPOINT也與CMD密切相關,可以修改容器啟動鏡像的方式。

RUN - 命令在我們構建 docker 鏡像時觸發。

CMD - 命令在我們啟動創建的 docker 鏡像時觸發。

我發現這篇文章非常有助於理解它們之間的區別:

RUN - RUN 指令允許您安裝您的應用程序和所需的包。 它在當前圖像之上執行任何命令,並通過提交結果創建一個新層。 通常,您會在 Dockerfile 中找到多個 RUN 指令。

CMD - CMD 指令允許您設置默認命令,該命令僅在您運行容器而不指定命令時執行。 如果 Docker 容器使用命令運行,則默認命令將被忽略。 如果 Dockerfile 有一個以上的 CMD 指令,除了最后一條指令
CMD 指令被忽略。

RUN - 安裝 Python ,您的容器現在已將 Python燒錄到其映像中
CMD - python hello.py ,運行你喜歡的腳本

現有答案涵蓋了查看此問題的任何人所需的大部分內容。 所以我將只介紹 CMD 和 RUN 的一些利基領域。

CMD:允許重復但浪費

GingerBeer 提出了一個重要觀點:如果你輸入多個 CMD,你不會得到任何錯誤 - 但這樣做很浪費。 我想用一個例子來詳細說明:

FROM busybox
CMD echo "Executing CMD"
CMD echo "Executing CMD 2"

如果你將它構建到一個鏡像中並在這個鏡像中運行一個容器,那么正如 GingerBeer 所說,只有最后一個 CMD 會被注意。 所以該容器的輸出將是:

執行 CMD 2

我的想法是“CMD”正在為正在構建的整個圖像設置一個全局變量,因此連續的“CMD”語句只是覆蓋對該全局變量的任何先前寫入,並且在構建的最終圖像中最后一個寫勝。 由於 Dockerfile 按從上到下的順序執行,我們知道最底層的 CMD 是獲得最后“寫入”的那個(比喻地說)。

RUN:如果圖像被緩存,命令可能不會執行

關於 RUN 需要注意的一個微妙點是,即使有副作用,它也被視為純函數,因此被緩存。 這意味着如果 RUN 有一些不會改變結果圖像的副作用,並且該圖像已經被緩存,那么 RUN 將不會再次執行,因此在后續構建中不會發生副作用。 例如,以這個 Dockerfile 為例:

FROM busybox
RUN echo "Just echo while you work"

第一次運行它時,你會得到這樣的輸出,帶有不同的字母數字 ID:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Running in ed37d558c505
Just echo while you work
Removing intermediate container ed37d558c505
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest

請注意,echo 語句是在上面執行的。 第二次運行它時,它使用緩存,並且您不會在構建的輸出中看到任何回聲:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Using cache
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest

注意:不要將 RUN 與 CMD 混淆。 RUN 實際運行一個命令並提交結果; CMD 在構建時不執行任何操作,而是指定映像的預期命令。

來自 docker 文件參考

https://docs.docker.com/engine/reference/builder/#cmd

RUN 命令:RUN 命令基本上會在我們構建映像時執行默認命令。 它還將為下一步提交圖像更改。

可以有 1 個以上的 RUN 命令,以幫助構建新映像的過程。

CMD 命令:CMD 命令只會為新容器設置默認命令。 這不會在構建時執行。

如果一個 docker 文件有 1 個以上的 CMD 命令,那么除了最后一個之外,所有這些命令都會被忽略。 由於此命令不會執行任何操作,只會設置默認命令。

RUN : 可以很多,在構建過程中使用,例如安裝多個庫

CMD : 只能有 1 個,這是你的執行起點(例如["npm", "start"] , ["node", "app.js"]

關於RUNCMD已經有足夠的答案了。 我只想在ENTRYPOINT上添加幾句話。 CMD參數可以被命令行參數覆蓋,而ENTRYPOINT參數總是被使用。

這篇文章是一個很好的信息來源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM