iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 23
2
DevOps

30 天與鯨魚先生做好朋友系列 第 23

了解 CMD 與 ENTRYPOINT

在寫 Dockerfile 或使用 docker run 時,我們使用 CMD 來執行指令。Docker 還設計了另一個類似的設定叫 ENTRYPOINT。活用這兩個設定將能讓 Docker image 使用更加靈活。

CMD 的設計

首先要強調一個重要的概念--container 就是 process。啟動 container 背後的原理就是啟動 process。

因此 Docker CMD 有個特性是,後面的設定會覆蓋前面的設定。比方說,以 alpine:3.12 的 Dockerfile 為例

FROM scratch
ADD alpine-minirootfs-3.12.0-x86_64.tar.gz /
CMD ["/bin/sh"]

這裡 CMD 的設定是 /bin/sh。FROM 它的 image 如 php:7.4-alpine

FROM alpine:3.12

# 略

CMD ["php", "-a"]

有設定新的 CMD 時,它會以後設定的為主。

docker run 是類似的情境,它是最後一關,先再看一次 docker run 的語法:

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

這裡的 [COMMAND] 指的就是 CMD。在下 docker run 沒有帶 COMMAND 的時候,它會使用 Dockerfile 定義的 CMD;如果有給,它就會覆蓋 CMD 設定。

也就是,下面這幾個例子結果是一樣的:

# Alpine
docker run --rm -it alpine:3.12
docker run --rm -it alpine:3.12 /bin/sh

# Node
docker run --rm -it php:7.4-alpine
docker run --rm -it php:7.4-alpine php -a

若想在 container 上執行其他指令,只要在後面接 COMMAND 即可:

# Alpine
docker run --rm -it alpine:3.12 ls

# Node
docker run --rm -it node:14-alpine node -v

這招在過去幾天裡很常拿來用,實際的意義就是取代 CMD 設定。

ENTRYPOINT 的設計

ENTRYPOINTCMD 很像,一樣是啟動 container 的時候會用到,所以一樣也會有後面設定覆蓋的狀況。

mysql:8 為例:

# 略
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 3306 33060
CMD ["mysqld"]

若將啟動 container 當成是執行指令的話,那 docker runENTRYPOINT 的關係就像下面這樣

# 等於在容器內執行 docker-entrypoint.sh mysqld
docker run --rm -it mysql:8

# 等於在容器內執行 docker-entrypoint.sh bash
docker run --rm -it mysql:8 bash

這時,我們可以做一個實驗:

# 使用 bash 進入 container
docker run --rm -it mysql:8 bash

# 在 container 裡執行 ENTRYPOINT + bash
docker-entrypoint.sh bash

# 在 container 裡執行 ENTRYPOINT + mysqld
docker-entrypoint.sh mysqld

沒錯,這就跟上面直接執行 docker run 結果一樣。相信這個實驗做完,就能理解 CMD 與 ENTRYPOINT 的差異與用法了。

今日自我回顧

了解 CMD 與 ENTRYPOINT 的設計後,接著就能開始設計更多變化的 image 了。

筆者病還沒好,已盡力打文章了。


上一篇
Network 手動配置
下一篇
活用 ENTRYPOINT
系列文
30 天與鯨魚先生做好朋友30

1 則留言

0
Ho.Chun
iT邦新手 5 級 ‧ 2021-08-19 08:39:37

不好意思 想問一下
如果只有 ENTRYPOINT 但沒有 CMD
同時 docker run 不給 CMD
這代表什麼意思呢 ?

看更多先前的回應...收起先前的回應...
Miles iT邦新手 3 級 ‧ 2021-08-19 12:56:55 檢舉

不能執行,Docker Daemon 會跟你說:

docker: Error response from daemon: No command specified.
See 'docker run --help'.
Miles iT邦新手 3 級 ‧ 2021-08-19 13:14:47 檢舉

等等,我好像誤會意義了。

有 ENTRYPOINT 沒有 CMD,這代表它只會拿 ENTRYPOINT 來執行,24天有個表格可以參考

https://ithelp.ithome.com.tw/articles/10251314

Ho.Chun iT邦新手 5 級 ‧ 2021-08-19 13:29:43 檢舉

原來如此! 感謝 /images/emoticon/emoticon41.gif

不過想再提問兩點

  1. ENTRYPOINTCMD 誰先執行,誰後執行 ?
    還是說 CMD 只是單純給 ENTRYPOINT 當作參數 ?

  2. 有看過網路上一些寫法

// 第一種,用 ENTRYPOINT,和用 CMD
ENTRYPOINT ["/bin/cat"]
CMD ["/etc/passwd"]

// 第二種,只用 ENTRYPOINT,不用 CMD
ENTRYPOINT ["/bin/cat", "/etc/passwd"]

// 第三種,不用 ENTRYPOINT,只用 CMD
CMD ["/bin/cat", "/etc/passwd"]

這三種寫法有什麼差別嗎 ?
還是他們間有什麼優劣嗎 ?

Miles iT邦新手 3 級 ‧ 2021-08-23 23:31:47 檢舉

沒有什麼優劣,單純只是排先後順序的問題

差別你剛分享的三種寫法,結果都是一樣的,所以一個是寫法上的差異

另一個就是 CMD 要取代比較容易,所以常會調整的指令可以放 CMD,ENTRYPOINT 則是放不常調整的。

Ho.Chun iT邦新手 5 級 ‧ 2021-08-26 17:45:21 檢舉

原來如此! 感謝您

我要留言

立即登入留言