Dockerfile中run、cmd和entrypoint之間的區別
- Docker
1.概述
在Dockerfile中,我們經常會遇到諸如run , cmd,或entrypoint類的指令。乍一看,它們全部用於指定和運行命令。但是它們之間有什麼區別?它們如何相互影響?
在本教程中,我們將回答這些問題。我們將介紹這些說明中的每一個做什麼以及它們如何工作。我們還將研究它們在構建映像和運行Docker容器中所扮演的角色。
2.設定
首先,讓我們創建一個腳本log-event.sh.它只是在文件中添加一行,然後打印它:
#!/bin/sh
echo `date` [email protected] >> log.txt;
cat log.txt;
現在,讓我們創建一個簡單的Dockerfile:
FROM alpine
ADD log-event.sh /
在不同情況下,通過將行附加到log.txt
3. run命令
當我們構建映像時,將run這意味著傳遞給run的命令將在新層的當前圖像之上執行。然後將結果提交到圖像。讓我們看看它的實際效果。
首先,我們將run指令添加到我們的Dockerfile中:
FROM alpine
ADD log-event.sh /
RUN ["/log-event.sh", "image created"]
其次,讓我們用以下內容建立我們的形象:
docker build -t myimage .
現在,我們希望有一個包含log.txt文件image created行。讓我們通過基於圖像運行一個容器來檢查這一點:
docker run myimage cat log.txt
當列出文件的內容時,我們將看到類似以下的輸出:
Fri Sep 18 20:31:12 UTC 2020 image created
如果我們多次運行容器,我們將看到日誌文件中的日期沒有更改。這是有道理的,因為**run步驟是在映像生成時執行的**,而不是在容器運行時執行的。
現在,讓我們再次建立我們的鏡像。我們注意到日誌中的創建時間沒有改變。發生這種情況是因為,如果Dockerfile不變,則Docker會緩存run指令的結果。如果要使緩存無效,則需要將–no-cache選項傳遞給build命令。
4. cmd命令
使用**cmd指令,我們可以指定在容器啟動時執行的默認命令。**讓我們將一個cmd條目添加到我們的Dockerfile中,並查看其工作方式:
...
RUN ["/log-event.sh", "image created"]
CMD ["/log-event.sh", "container started"]
構建完映像後,現在讓我們運行它並檢查輸出:
$ docker run myimage
Fri Sep 18 18:27:49 UTC 2020 image created
Fri Sep 18 18:34:06 UTC 2020 container started
如果我們多次運行,我們將看到image created的圖像條目保持不變。但是container started每次運行都會啟動條目更新。這顯示了每次容器啟動時cmd
注意,這次我們使用了稍微不同的docker run命令來啟動我們的容器。讓我們看看如果運行與之前相同的命令會發生什麼:
$ docker run myimage cat log.txt
Fri Sep 18 18:27:49 UTC 2020 image created
這次將忽略Dockerfile中指定cmd那是因為我們為docker run命令指定了參數。
現在讓我們繼續前進,看看如果Dockerfile中cmd讓我們添加一個新條目,該條目將顯示另一條消息:
...
RUN ["/log-event.sh", "image created"]
CMD ["/log-event.sh", "container started"]
CMD ["/log-event.sh", "container running"]
構建映像並再次運行容器後,我們將找到以下輸出:
$ docker run myimage
Fri Sep 18 18:49:44 UTC 2020 image created
Fri Sep 18 18:49:58 UTC 2020 container running
如我們所見, container started項不存在,只有container running .這是因為,如果指定了多個cmd,則僅調用最後一個cmd。
5. entrypoint命令
正如我們在上面看到的,如果在啟動容器時傳遞任何參數,則將忽略cmd如果我們想要更大的靈活性怎麼辦?假設我們要自定義附加文本並將其作為參數傳遞給docker run命令。為此,讓我們使用entrypoint.我們將指定在容器啟動時運行的默認命令。而且,我們現在能夠提供額外的參數。
讓我們用entrypoint: cmd
...
RUN ["/log-event.sh", "image created"]
ENTRYPOINT ["/log-event.sh"]
現在,通過提供一個自定義文本條目來運行容器:
$ docker run myimage container running now
Fri Sep 18 20:57:20 UTC 2020 image created
Fri Sep 18 20:59:51 UTC 2020 container running now
我們可以看到**entrypoint行為與****cmd** .另外,它允許我們自定義在啟動時執行的命令。
與cmd一樣,在有多個entrypoint條目的情況下,僅考慮最後一個條目。
cmd與entrypoint之間的交互
我們已經使用cmd和entrypoint來定義運行容器時執行的命令。現在讓我們繼續前進,看看如何結合使用cmd和entrypoint 。
一種這樣的用例是為entrypoint.讓我們在Dockerfile中的入口點之後cmd entrypoint
...
RUN ["/log-event.sh", "image created"]
ENTRYPOINT ["/log-event.sh"]
CMD ["container started"]
現在,讓我們在不提供任何參數的情況下運行容器,並使用cmd指定的默認值:
$ docker run myimage
Fri Sep 18 21:26:12 UTC 2020 image created
Fri Sep 18 21:26:18 UTC 2020 container started
如果選擇這樣做,我們也可以覆蓋它們:
$ docker run myimage custom event
Fri Sep 18 21:26:12 UTC 2020 image created
Fri Sep 18 21:27:25 UTC 2020 custom event
需要注意的是entrypoint以外殼形式使用時的不同行為。讓我們更新Dockerfile中entrypoint
...
RUN ["/log-event.sh", "image created"]
ENTRYPOINT /log-event.sh
CMD ["container started"]
在這種情況下,運行容器時,我們將看到Docker如何忽略傳遞給docker run或cmd任何參數。
7.結論
在本文中,我們已經看到了Docker指令之間的差異和相似之處: run , cmd,和entrypoint 。我們已經觀察到它們在什麼時候被調用。此外,我們還研究了它們的用途以及它們如何協同工作。