[Docker 學習筆記] ENTRYPOINT 和 CMD 的分別和用法

Dockerfile 寫起來相信大家都有一個疑問, ENTRYPOINT 和 CMD 的分別是什麼?

根據 Docker 的官方文檔

An ENTRYPOINT allows you to configure a container that will run as an executable.

The main purpose of a CMD is to provide defaults for an executing container.

看完也不太懂, 繼續向下看

Both CMD and ENTRYPOINT instructions define what command gets executed when running a container. There are few rules that describe their co-operation.

  1. Dockerfile should specify at least one of CMD or ENTRYPOINT commands.
  2. ENTRYPOINT should be defined when using the container as an executable.
  3. CMD should be used as a way of defining default arguments for an ENTRYPOINT command or for executing an ad-hoc command in a container.
  4. CMD will be overridden when running the container with alternative arguments.

結論

簡單直接, ENTRYPOINT 是 Image 運行時 Container 要運行的 Executable
而 CMD 是 ENTRYPOINT 預設的 Argument (參數), 執行時可以被命令行取代

舉個例子, 這個 Dockerfile
運行起來

# Ping 127.0.0.1
docker run test
# Ping 8.8.8.8
docker run test 8.8.8.8

注意事項

1. ENTRYPOINT 和 CMD 都有兩個格式 (JSON Array 和 shell), 官方文檔舉的例子
其中一個用了 shell 格式的話,
紅字部分, CMD 被忽略了, 無法達到我們預期的效果
藍字部分, /bin/sh -c 亂入了, 會令執行起來添加多了一個 bash 進程, PID 不是 1

簡單說, 用 JSON Array 格式就不會錯了

No ENTRYPOINT ENTRYPOINT exec_entry p1_entry ENTRYPOINT [“exec_entry”, “p1_entry”]
No CMD error, not allowed /bin/sh -c exec_entry p1_entry exec_entry p1_entry
CMD [“exec_cmd”, “p1_cmd”] exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry exec_cmd p1_cmd
CMD [“p1_cmd”, “p2_cmd”] p1_cmd p2_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry p1_cmd p2_cmd
CMD exec_cmd p1_cmd /bin/sh -c exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

2. ENTRYPOINT 和 CMD 在 Dockerfile 忽略不填的話, 會繼承母 Image 的數值

3. 填寫 ENTRYPOINT 必須同時填寫 CMD, 因為重寫 ENTRYPOINT 會清空 CMD 數值

命令懶人包

# 直接運行 (套用預設 ENTRYPOINT + CMD)
docker run test

# 修改 CMD 運行 (只套用預設 ENTRYPOINT)
docker run test 8.8.8.8

# 修改 ENTRYPOINT 運行 (只套用預設 CMD, 無法這樣使用!)
# docker run --entrypoint=nslookup test

# 修改 ENTRYPOINT + CMD 運行
docker run --entrypoint=nslookup test 8.8.8.8

另外 Override ENTRYPOINT 的話不能直接在 ENTRYPOINT 提供 Argument
需要 Argument 的話要再在後面 CMD 的位置提供

參考: https://medium.com/@oprearocks/how-to-properly-override-the-entrypoint-using-docker-run-2e081e5feb9d

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.