dockerfile中CMD和ENTRYPOINT指令使用及說明
1、exec和shell兩種風(fēng)格
無論是CMD還是ENTRYPOINT指令,都支持exec和shell兩種風(fēng)格:
語法 | 示例 | 解析方式 | |
Exec 形式 | JSON 數(shù)組 | CMD ["sleep", "60"] | 直接執(zhí)行二進(jìn)制程序,docker實(shí)際運(yùn)行execve("sleep", ["sleep", "60"]) |
Shell 形式 | 字符串 | CMD sleep 60 | 通過 shell 執(zhí)行命令,相當(dāng)于 /bin/sh -c "sleep 60" |
說明:execve時(shí)Linux內(nèi)核的一個(gè)系統(tǒng)調(diào)用,作用事用于一個(gè)新程序替換當(dāng)前進(jìn)程(把新程序加載到當(dāng)前進(jìn)程的內(nèi)存空間,當(dāng)前的進(jìn)程會(huì)被丟棄)
注意:生產(chǎn)環(huán)境中推薦使用Exec形式,更安全、可控。
1)shell風(fēng)格和exec風(fēng)格解析方式:
shell風(fēng)格是通過shell執(zhí)行的命令,
CMD sleep 60 #Docker實(shí)際運(yùn)行時(shí)會(huì)變成 /bin/sh -c "sleep 60"
也就是說,它先啟動(dòng)一個(gè) Shell 進(jìn)程(/bin/sh),再讓這個(gè) shell 去執(zhí)行 sleep 60。所以:
• 容器的 PID 1 進(jìn)程 實(shí)際是 /bin/sh,不是 sleep
• Shell 風(fēng)格中,可以解釋變量、重定向符、管道符等(比如 CMD echo $PATH > /tmp/p)
而對于exec風(fēng)格是直接執(zhí)行命令,
CMD ["sleep", "60"]
#DOcker不會(huì)提懂/bin/sh,而是直接執(zhí)行命令
execve("sleep", ["sleep", "60"])所以,
- 容器內(nèi)的 PID 1 就是 sleep 進(jìn)程;
- 命令參數(shù)直接傳遞給進(jìn)程;
- 不支持 shell 特性(如 $VAR、|、> 等);
- 啟動(dòng)更快、行為更一致。
2)環(huán)境變量展開:(CDM和ENTRYPOINT是一樣的)
FROM busybox ENV NAME=KnowLiu # shell 形式 CMD echo "Hello $NAME" #運(yùn)行 docker run myimage # 輸出:Hello KnowLiu #------------- FROM busybox ENV NAME=KnowLiu CMD ["echo", "Hello $NAME"] #運(yùn)行 docker run myimage # 輸出:Hello $NAME
結(jié)論:
- Shell 形式支持變量展開;
- Exec 形式不支持(因?yàn)闆]經(jīng)過 shell)。
3)信號轉(zhuǎn)發(fā):(CDM和ENTRYPOINT是一樣的)
FROM busybox CMD ["sleep", "1000"] #運(yùn)行,然后停止容器會(huì)立即停止 docker run --name test mini docker stop test #----------- FROM busybox CMD sleep 1000 #運(yùn)行,然后停止容器,容器停止會(huì)超時(shí) docker run --name test mini docker stop test
說明:由于/bin/sh是1號進(jìn)程,SIGTERM 發(fā)給 shell,而 shell 默認(rèn)不會(huì)轉(zhuǎn)發(fā)信號,導(dǎo)致 sleep 不退出 → 容器停止會(huì)超時(shí)。
4)參數(shù)傳遞:
#docker file FROM alpine:3.20 ENTRYPOINT ["echo", "hahaha!"] #構(gòu)建、運(yùn)行 docker build -t my-test . docker run my-test 輸出 hahaha! docker run my-test hi 輸出 hahaha! hi docker run my-test echo hi 輸出 hahaha! echo hi #------------------------ #docker file FROM alpine:3.20 ENTRYPOINT echo hahaha #構(gòu)建、運(yùn)行 docker build -t my-test . docker run my-test 輸出 hahaha docker run my-test hi 輸出 hahaha docker run my-test echo hi 輸出 hahaha
可以看到,ENTRYPOINT指令的exec風(fēng)格支持傳遞參數(shù),shell風(fēng)格不支持!關(guān)于命令覆蓋,見下面!
5)總結(jié)二者的區(qū)別:
特性 | Exec 形式 | Shell 形式 |
寫法 | CMD ["cmd", "arg1", "arg2"] ENTRYPOINT ["cmd", "arg1", "arg2"] | CMD cmd arg1 arg2 ENTRYPOINT cmd arg1 arg2 |
是否通過 /bin/sh | ? 否 | ? 是 |
是否支持環(huán)境變量展開 | ? 否 | ? 是 |
是否支持管道、重定向等 | ? 否 | ? 是 |
信號傳遞(SIGTERM 等) | ? 正常 | ?? 可能被攔截 |
運(yùn)行時(shí)參數(shù)(docker run 參數(shù)) | ? 支持,僅針對對ENTRYPOINT指令,CMD指令是命令覆蓋 | ? 否,僅針對對ENTRYPOINT指令,CMD指令是命令覆蓋 |
PID 1 是誰 | 應(yīng)用進(jìn)程 | /bin/sh |
推薦場景 | 長期運(yùn)行的服務(wù)、生產(chǎn)環(huán)境 | 臨時(shí)命令、調(diào)試腳本 |
性能 | 更快、更干凈 | 稍慢 |
2、CMD、ENTRYPOINT指令
1)基本:
二者都是用來提供容器啟動(dòng)時(shí)的命令,都支持exec和shell兩種書寫風(fēng)格:
- CMD提供的是默認(rèn)命令,所以支持命令的覆蓋;此外,還可以作為為 ENTRYPOINT 指令提供默認(rèn)參數(shù)(ENTRYPOINT+CMD組合方式,并且使用exec風(fēng)格)
- ENTRYPOINT是固定的命令,不支持命令覆蓋,可以進(jìn)行參數(shù)的傳遞。
ENTRYPOINT雖然默認(rèn)不能命令的覆蓋,但是可以通過--entrypoint參數(shù)來實(shí)現(xiàn):
docker run --entrypoint <新命令> <鏡像名> [參數(shù)...]
看個(gè)例子
#dockerfile FROM alpine:3.20 ENTRYPOINT ["echo", "hahaha!"] #構(gòu)建 docker build -t mytest #運(yùn)行 docker run mytest #輸出 hahaha! docker run --entrypoint ls mytest /usr 輸出 bin lib local sbin share
注意:在dockerfile中如果有多個(gè)CMD、ENTRYPOING指令,那么最后一個(gè)會(huì)覆蓋前面的。
2)一句話區(qū)分CMD和ENTRYPOINT:
- CMD:提供容器啟動(dòng)的默認(rèn)命令或參數(shù),可以被覆蓋(被entrypoint覆蓋,或者被docker run后面跟的命令覆蓋)
- ENTRYPOINT:定義容器啟動(dòng)時(shí)固定要執(zhí)行的主命令,一般不會(huì)覆蓋(除非使用--entrypoint)
示例1:使用CMD:
#dockerfile FROM busybox CMD ["echo", "hello world"] #構(gòu)建 docker build -t mytest #運(yùn)行 docker run mytest #輸出 hello world # 運(yùn)行 docker run myimage echo hi # 輸出:hi
說明:CMD 定義的命令可以被你在 docker run 中輸入的新命令替換掉。
示例2:ENTRYPOINT示例:
#dockerfile FROM busybox ENTRYPOINT ["echo", "hello"] # 運(yùn)行 docker run myimage # 輸出:hello #運(yùn)行 docker run myimage world # 輸出:hello world
說明:這里 ENTRYPOINT 是固定命令 echo,而 docker run myimage world 中的參數(shù) world 會(huì)被當(dāng)作 ENTRYPOINT 的參數(shù)。
示例3:你可以 組合 ENTRYPOINT + CMD 來實(shí)現(xiàn)“固定命令 + 默認(rèn)參數(shù)”模式
#dockerfile FROM busybox ENTRYPOINT ["sleep"] CMD ["60"] #運(yùn)行 docker run myimage # 等價(jià)于:sleep 60 docker run myimage 10 # 等價(jià)于:sleep 10
說明:
- ENTRYPOINT 是固定的命令:sleep
- CMD 提供默認(rèn)參數(shù):60
- 用戶在 docker run 中輸入?yún)?shù)會(huì)覆蓋 CMD,但不會(huì)影響 ENTRYPOINT
3、docker run運(yùn)行容器時(shí)的命令覆蓋和參數(shù)傳遞
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
[COMMAND] 和 [ARG...] 到底是「命令覆蓋」還是「參數(shù)傳遞」,取決于 Dockerfile 的 ENTRYPOINT/CMD 組合形式。
Dockerfile 內(nèi)容 | 啟動(dòng)行為 | docker run IMAGE ... 的效果 |
1?? 只有 CMD | CMD 是默認(rèn)命令 | 運(yùn)行時(shí)的 [COMMAND] 會(huì) 覆蓋 CMD |
2?? 只有 ENTRYPOINT | ENTRYPOINT 是固定命令 | 對于exec風(fēng)格下,運(yùn)行時(shí)的 [COMMAND] 會(huì)被 當(dāng)作參數(shù)傳遞給 ENTRYPOINT |
3?? ENTRYPOINT + CMD | ENTRYPOINT 是固定命令,CMD 提供默認(rèn)參數(shù) | 對于exec風(fēng)格下,運(yùn)行時(shí)的 [COMMAND] 會(huì) 覆蓋 CMD(參數(shù)部分),但 不會(huì)覆蓋 ENTRYPOINT |
1)示例1:CMD 的shell和exec風(fēng)格:
#docker file FROM alpine:3.20 CMD echo hello #構(gòu)建、運(yùn)行 docker build -t my-test . docker run my-test 輸出 hello docker run my-test echo hi 輸出 hi docker run my-test hi 報(bào)錯(cuò),“hi” executable file not found in $PATH: unknown.
說明:將dockerfile替換成CMD ["echo", "hello"] 運(yùn)行結(jié)果一樣!所以,對于CMD指令來說,只有ENTRYPOINT + CMD的組合的時(shí)候,才能通過docker run傳遞參數(shù)給CMD,只有CMD的時(shí)候,傳遞的“字符串”都是當(dāng)命令來執(zhí)行的,無法單獨(dú)為其傳遞參數(shù)!
2)示例2:ENTRYPOINT的shell風(fēng)格:
#docker file FROM alpine:3.20 ENTRYPOINT echo hahaha #構(gòu)建、運(yùn)行 docker build -t my-test . docker run my-test 輸出 hahaha docker run my-test hi 輸出 hahaha docker run my-test echo hi 輸出 hahaha
說明:對于ENTRYPOINT的shell風(fēng)格,無法傳遞參數(shù)!
3)示例3:ENTRYPOINT的exec風(fēng)格:
#docker file FROM alpine:3.20 ENTRYPOINT ["echo", "hahaha!"] #構(gòu)建、運(yùn)行 docker build -t my-test . docker run my-test 輸出 hahaha! docker run my-test hi 輸出 hahaha! hi docker run my-test echo hi 輸出 hahaha! echo hi
說明:對于ENTRYPOINT的Exec風(fēng)格,傳遞的字符串會(huì)當(dāng)作參數(shù)傳遞,并追加進(jìn)去!
4)示例4:組合模式exec風(fēng)格
#docker file FROM alpine:3.20 ENTRYPOINT ["echo"] CMD ["hi"] #構(gòu)建、運(yùn)行 docker build -t my-test . docker run my-test 輸出 hi docker run my-test abc 輸出 abc docker run my-test echo 123 輸出 echo 123
說明:docker run后面的字符串,會(huì)當(dāng)作參數(shù)覆蓋CMD。
5)示例5:組合模式shell風(fēng)格
#docker file FROM alpine:3.20 ENTRYPOINT echo CMD hi #構(gòu)建、運(yùn)行 docker build -t my-test . docker run my-test 輸出 空 docker run my-test abc 輸出 空 docker run my-test echo 123 輸出 空
說明:
docker官方文檔描述:
When using the exec form of ENTRYPOINT, the CMD value is passed as arguments to ENTRYPOINT.When using the shell form of ENTRYPOINT, the CMD value is ignored.
也就是說, Shell 形式的 ENTRYPOINT 會(huì)忽略 CMD 的內(nèi)容。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
skywalking agent 關(guān)聯(lián)docker鏡像的多種方法
Apache SkyWalking 提供了多種方式來部署和使用 SkyWalking Agent,包括在 Docker 容器中運(yùn)行的應(yīng)用,本文給大家分享幾種方式將 SkyWalking Agent 集成到你的 Docker 應(yīng)用中,感興趣的朋友一起看看吧2025-04-04
harbor如何更改網(wǎng)段(docker-compose)
文章介紹了解決Harbor安裝后網(wǎng)段沖突問題的步驟,首先,查看當(dāng)前Docker網(wǎng)橋并獲取網(wǎng)橋ID,然后,關(guān)閉Harbor服務(wù),刪除所有容器和網(wǎng)橋,接著,修改harbor的docker-compose.yaml文件,添加新的網(wǎng)絡(luò)配置,最后,驗(yàn)證服務(wù)是否正常運(yùn)行,并確保修改不會(huì)被覆蓋2026-03-03
Ubuntu?環(huán)境下安裝?Docker環(huán)境詳解
這篇文章主要介紹了Ubuntu?環(huán)境下安裝?Docker環(huán)境詳解的相關(guān)資料,需要的朋友可以參考下2022-10-10
配置gpu驅(qū)動(dòng)、docker和vllm過程
文章主要介紹了在Ubuntu 22.04上安裝Docker并運(yùn)行vllm模型的具體步驟,包括安裝驅(qū)動(dòng)、卸載舊版本Docker、更新系統(tǒng)軟件包、添加Docker官方GPG密鑰和阿里云Docker軟件源、安裝Docker、加入docker組、驗(yàn)證安裝、拉取vllm鏡像、下載模型、配置docker-compose2026-05-05
docker pull鏡像報(bào)錯(cuò):‘invalid checksum digest 
鏡像推送/拉取報(bào)錯(cuò),排查發(fā)現(xiàn)倉庫正常但Docker默認(rèn)連接443端口,配置了安全連接,最終因宿主機(jī)443端口被占用,停掉沖突服務(wù)后問題解決2025-08-08
Docker Engine配置的實(shí)現(xiàn)步驟
Docker配置文件位于/etc/docker/daemon.json,下面就來介紹了Docker Engine配置方法,涵蓋配置文件位置、常用參數(shù),如存儲(chǔ)路徑、調(diào)試模式、網(wǎng)絡(luò)設(shè)置、日志驅(qū)動(dòng)等,感興趣的可以了解一下2025-07-07
docker?運(yùn)行花生殼實(shí)現(xiàn)內(nèi)外網(wǎng)穿透的詳細(xì)過程
這篇文章主要介紹了docker?運(yùn)行花生殼實(shí)現(xiàn)內(nèi)外網(wǎng)穿透,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03

