ENTRYPOINT是 Dockerfile 定義的一個指令,他的作用類似於 CMD,都是在 container 啟動時會自動執行的指令,你可以不定義 CMD,然後改成定義 ENTRYPOINT,你的 container 照樣能夠啟動,如同你之前將命令寫在 CMD 一樣。
那我們為什麼需要 ENTRYPOINT 呢?
因為 ENTRYPOINT 不只擁有取代 CMD 的功能,更重要的還有與 CMD「合用」的功能,如果你同時定義了 ENTRYPOINT 與 CMD,那這兩個指令將會合而為一,組在一起執行。
例如:
ENTRYPOINT ["curl"]
CMD ["http://dummy-url.com/"]
container 啟動時會執行
curl http://dummy-url.com/
shell form
命令格式
ENTRYPOINT command param1 param2
如果你以 shell form 來寫 ENTRYPOINT,那麼你將失去 ENTRYPOINT 能與 CMD 合用的這個功能,舉上面的例子來看:
產出指令會是 curl
但這種指令有一個優點,就是他預設以 /bin/sh -c
執行,所以剛剛的結果最終其實是 /bin/sh -c curl
,因此他能接受環境變數傳入當參數,像是你的 ENTRYPOINT 可以寫成這樣 ENTRYPOINT curl ${url}
,只要你在環境變數中有定義 url
,那麼你就能取到這個值。
exec form
ENTRYPOINT [“executable”, “param1”, “param2”]
這是官方較推薦的使用格式,他的特性恰恰與 shell form 相反,
exec form 可以與 CMD 合用
但要注意的是 CMD 的指令格式也必須是 exec form:
ENTRYPOINT [“curl”]
CMD [“http://dummy-url.com/”]
產出指令會是 curl http://dummy-url.com/
另一個要特別注意的一點是 exec form 不會以 /bin/sh -c
執行,也就是說他不能直接讀取環境變數的值,但好消息是你能夠透過手動指定執行環境來克服這點,例如手動加 /bin/sh -c
:
ENTRYPOINT [ “/bin/sh”, “-c”, “echo $HOME” ]
举个例子
- 替換經常變動的參數
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
通常會把穩定的參數放在 ENTRYPOINT,像是 -b
,也就是你希望每個 container 都需要執行到的指令
另一方面,則會把會經常變動的參數放在 CMD
,代表你希望不同 container 可以使用不同參數,而 -c
是預設行為。
只要你想更改這個預設行為,你可以直接通過指令更改:
docker run -it --rm --name test top -H
如此一來最後執行到的就會是 top -b -H
- 在 container 啟動前進行初始化設定
我們透過 mysql 的 Dockerfille 來說明
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306 33060
CMD ["mysqld"]
在執行 mysqld
之前,執行了一個 docker-entrypoint.sh
的 script,我們接著來看看這個 script
if [ -n "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)"
mysql_note "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
這是其中一段,你會發現這個 script 讀取了環境變數 $MYSQL_RANDOM_ROOT_PASSWORD
,並依照值做初始化的動作。ENTRYPOINT 讓你有機會在 CMD 執行之前做一些事。
以上就是關於 ENTRYPOINT 的介紹,如果有不懂或寫不好的地方都歡迎和我說哦!