我們?cè)谏掀∽魑腫docker容器dockerfile詳解]對(duì)中dockerfile有了比較全面的認(rèn)識(shí),我們也提到`ENTRYPOINT`和`CMD`都可以指定容器啟動(dòng)命令。因?yàn)檫@兩個(gè)命令是掌握dockerfile編寫的核心,所以這邊還是單獨(dú)拿出來再講一講。
![](/d/20211016/ada0544dc1db562bd067b8f2486d703b.gif)
一、寫在前面
我們?cè)谏掀∽魑膁ocker容器dockerfile詳解對(duì)中dockerfile有了比較全面的認(rèn)識(shí),我們也提到ENTRYPOINT
和CMD
都可以指定容器啟動(dòng)命令。因?yàn)檫@兩個(gè)命令是掌握dockerfile編寫的核心,所以這邊還是單獨(dú)拿出來再講一講。
二、CMD 與 ENTRYPOINT主要區(qū)別
我們直接進(jìn)入主題,CMD 與 ENTRYPOINT都是用于指定啟動(dòng)容器執(zhí)行的命令,區(qū)別在于:
- 當(dāng)docker run 命令中有參數(shù)時(shí),守護(hù)進(jìn)程會(huì)忽略CMD命令。
- 使用ENTRYPOINT指令不會(huì)忽略,并且會(huì)接收docker run 參數(shù)附加到命令行中。
為了使構(gòu)建的容器可以正常啟動(dòng),我們編寫的dockerfile文件必須包含一個(gè)CMD或ENTRYPOINT指令。
三、CMD 與 ENTRYPOINT的結(jié)合使用
1.CMD
CMD
指令有三種形式:
CMD ["executable","param1","param2"]
(exec形式,這是首選形式)
CMD ["param1","param2"]
(作為ENTRYPOINT 的默認(rèn)參數(shù))
CMD command param1 param2
(shell形式)
dockerfile文件中包含多個(gè)CMD時(shí),只有最后一個(gè)被加載使用。
我們?cè)赿ockerhub中搜索centos官方鏡像,看一下的官方dockerfile文件。
![](/d/20211016/2d3393cb2cbe601e8527fefa26649374.gif)
基本上每一個(gè)官方鏡像都會(huì)為我們提供各自版本的dockerfile鏈接,如下:
![](/d/20211016/51cc7ac3f100b427da2cfcf9a8a2558f.gif)
我們查看latest
標(biāo)簽的dockerfile
FROM scratch
ADD centos-8-x86_64.tar.xz /
LABEL org.label-schema.schema-version="1.0" org.label-schema.name="CentOS Base Image" org.label-schema.vendor="CentOS" org.label-schema.license="GPLv2" org.label-schema.build-date="20201204"
CMD ["/bin/bash"]
只有四行,這就是構(gòu)建一個(gè)latest
版本centos8.3.2011鏡像的dockerfile全部?jī)?nèi)容。指定基鏡像(這里從scratch這個(gè)空鏡像開始構(gòu)建),添加rootfs內(nèi)容,打標(biāo)簽,通過CMD指定啟動(dòng)命令。
不止centos,其他debian、ubuntu、busybox等鏡像都只需通過CMD指定啟動(dòng)命令。比如busybox更為簡(jiǎn)約:
FROM scratch
ADD busybox.tar.xz /
CMD ["sh"]
這種基礎(chǔ)類、工具類鏡像的構(gòu)建我們只需要指定一個(gè)必要CMD來啟動(dòng)容器即可。但是我們編寫一個(gè)dockerfile并不是為了啟動(dòng)容器而編寫,大多數(shù)時(shí)候我們要在容器運(yùn)行我們的app,運(yùn)行我們的服務(wù)。
當(dāng)然通過CMD也可以啟動(dòng),可是如此一來有一個(gè)缺陷,我們上面說到的CMD的啟動(dòng)命令會(huì)被docker run 參數(shù)代替。
我們有下面Dockerfile
[root@localhost dockerfiles]# cat Dockerfile
FROM centos
CMD ["/bin/top","-b"]
構(gòu)建后,使用參數(shù)ps啟動(dòng)容器。
[root@localhost dockerfiles]# docker run -it centos_top:v1 ps
PID TTY TIME CMD
1 pts/0 00:00:00 ps
可看看到啟動(dòng)容器后top -b
已經(jīng)被替換為ps,并非實(shí)現(xiàn)參數(shù)的替換。顯然這不是我們想要的。有沒有什么辦法既可以默認(rèn)啟動(dòng)應(yīng)用,又可以加載到docker run 參數(shù)?這就是接下來ENTRYPOINT與CMD的妙用。
2.ENTRYPOINT結(jié)合CMD
ENTRYPOINT
的exec和shell形式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
上面我們提到CMD ["param1","param2"]
形式可以作為ENTRYPOINT參數(shù),同時(shí)ENTRYPOINT 指定的命令無法被docker run 參數(shù)取代。假如我們把CMD和ENTRYPOINT兩個(gè)指令相結(jié)合,這樣我們就可以通過CMD來接收docker run 參數(shù),然后把參數(shù)傳遞給ENTRYPOINT執(zhí)行。
我們以nginx官方dockerfile latest版本1.21為例
![](/d/20211016/5efa6bb3f0acd7dbf17b89e72d1c52e7.gif)
首先我們查看Dockerfile
,這里我們只關(guān)注啟動(dòng)命令,如下:
...
COPY docker-entrypoint.sh /
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 80
STOPSIGNAL SIGQUIT
CMD ["nginx", "-g", "daemon off;"]
從上面我們可以看到,在啟動(dòng)nginx容器時(shí)首先運(yùn)行docker-entrypoint.sh
腳本并把CMD命令中的參數(shù)nginx -g "daemon off;"
傳遞進(jìn)來。即docker run不添加參數(shù)時(shí)啟動(dòng)容器相當(dāng)于執(zhí)行如下腳本與默認(rèn)參數(shù)。
#docker-entrypoint.sh nginx -g "daemon off;"
當(dāng)我們使用docker run 傳入?yún)?shù)會(huì)怎樣?
我傳入nginx-debug
#docker run -dt nginx nginx-debug -g "daemon off;"
此時(shí)啟動(dòng)容器相當(dāng)于執(zhí)行如下腳本與參數(shù)
#docker-entrypoint.sh nginx-debug -g "daemon off;"
我們通過ps來看一下我們啟動(dòng)的容器
[root@localhost dockerfiles]# ps -ef|grep nginx
root 6327 6306 0 Aug12 pts/0 00:00:00 nginx: master process nginx -g daemon off;
101 6384 6327 0 Aug12 pts/0 00:00:00 nginx: worker process
101 6385 6327 0 Aug12 pts/0 00:00:00 nginx: worker process
root 16800 16780 3 12:51 pts/0 00:00:00 nginx: master process nginx-debug -g daemon off;
101 16857 16800 0 12:51 pts/0 00:00:00 nginx: worker process
101 16858 16800 0 12:51 pts/0 00:00:00 nginx: worker process
顯然我們兩種參數(shù)nginx、nginx-debug的容器都啟動(dòng)成功!
也就是說我們通過ENTRYPOINT ["/docker-entrypoint.sh"]
指定的命令在啟動(dòng)時(shí)無論如何都會(huì)執(zhí)行,并且可以接收到了docker run 的參數(shù)。
docker-entrypoint.sh是什么?docker-entrypoint.sh這是一個(gè)預(yù)處理腳本通常用來過濾命令行參數(shù)或者執(zhí)行exec 來啟動(dòng)容器為1的進(jìn)程。
通過ENTRYPOINT+CMD實(shí)現(xiàn)命令默認(rèn)參數(shù)或接收docker run 參數(shù)是一種非常流行并且有用的dockerfile編寫方式。
到此這篇關(guān)于dockerfile中ENTRYPOINT與CMD的結(jié)合的文章就介紹到這了,更多相關(guān)dockerfile中ENTRYPOINT與CMD內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!