我們在上篇小作文[docker容器dockerfile詳解]對中dockerfile有了比較全面的認識,我們也提到`entrypoint`和`cmd`都可以指定容器啟動命令。因為這兩個命令是掌握dockerfile編寫的核心,所以這邊還是單獨拿出來再講一講。
一、寫在前面
我們在上篇小作文對docker容器dockerfile詳解中dockerfile有了比較全面的認識,我們也提到entrypoint
和cmd
都可以指定容器啟動命令。因為這兩個命令是掌握dockerfile編寫的核心,所以這邊還是單獨拿出來再講一講。
二、cmd 與 entrypoint主要區別
我們直接進入主題,cmd 與 entrypoint都是用于指定啟動容器執行的命令,區別在于:
- 當docker run 命令中有參數時,守護進程會忽略cmd命令。
- 使用entrypoint指令不會忽略,并且會接收docker run 參數附加到命令行中。
為了使構建的容器可以正常啟動,我們編寫的dockerfile文件必須包含一個cmd或entrypoint指令。
三、cmd 與 entrypoint的結合使用
1.cmd
cmd
指令有三種形式:
-
cmd ["executable","param1","param2"]
(exec形式,這是首選形式) -
cmd ["param1","param2"]
(作為entrypoint 的默認參數) -
cmd command param1 param2
(shell形式)
dockerfile文件中包含多個cmd時,只有最后一個被加載使用。
我們在dockerhub中搜索centos官方鏡像,看一下的官方dockerfile文件。
基本上每一個官方鏡像都會為我們提供各自版本的dockerfile鏈接,如下:
我們查看latest
標簽的dockerfile
1
2
3
4
|
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" ] |
只有四行,這就是構建一個latest
版本centos8.3.2011鏡像的dockerfile全部內容。指定基鏡像(這里從scratch這個空鏡像開始構建),添加rootfs內容,打標簽,通過cmd指定啟動命令。
不止centos,其他debian、ubuntu、busybox等鏡像都只需通過cmd指定啟動命令。比如busybox更為簡約:
1
2
3
|
from scratch add busybox. tar .xz / cmd [ "sh" ] |
這種基礎類、工具類鏡像的構建我們只需要指定一個必要cmd來啟動容器即可。但是我們編寫一個dockerfile并不是為了啟動容器而編寫,大多數時候我們要在容器運行我們的app,運行我們的服務。
當然通過cmd也可以啟動,可是如此一來有一個缺陷,我們上面說到的cmd的啟動命令會被docker run 參數代替。
我們有下面dockerfile
1
2
3
|
[root@localhost dockerfiles] # cat dockerfile from centos cmd [ "/bin/top" , "-b" ] |
構建后,使用參數ps啟動容器。
1
2
3
|
[root@localhost dockerfiles] # docker run -it centos_top:v1 ps pid tty time cmd 1 pts /0 00:00:00 ps |
可看看到啟動容器后top -b
已經被替換為ps,并非實現參數的替換。顯然這不是我們想要的。有沒有什么辦法既可以默認啟動應用,又可以加載到docker run 參數?這就是接下來entrypoint與cmd的妙用。
2.entrypoint結合cmd
entrypoint
的exec和shell形式:
-
entrypoint ["executable", "param1", "param2"]
-
entrypoint command param1 param2
上面我們提到cmd ["param1","param2"]
形式可以作為entrypoint參數,同時entrypoint 指定的命令無法被docker run 參數取代。假如我們把cmd和entrypoint兩個指令相結合,這樣我們就可以通過cmd來接收docker run 參數,然后把參數傳遞給entrypoint執行。
我們以nginx官方dockerfile latest版本1.21為例
首先我們查看dockerfile
,這里我們只關注啟動命令,如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
... 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;" ] |
從上面我們可以看到,在啟動nginx容器時首先運行docker-entrypoint.sh
腳本并把cmd命令中的參數nginx -g "daemon off;"
傳遞進來。即docker run不添加參數時啟動容器相當于執行如下腳本與默認參數。
1
|
#docker-entrypoint.sh nginx -g "daemon off;" |
當我們使用docker run 傳入參數會怎樣?
我傳入nginx-debug
1
|
#docker run -dt nginx nginx-debug -g "daemon off;" |
此時啟動容器相當于執行如下腳本與參數
1
|
#docker-entrypoint.sh nginx-debug -g "daemon off;" |
我們通過ps來看一下我們啟動的容器
1
2
3
4
5
6
7
|
[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 |
顯然我們兩種參數nginx、nginx-debug的容器都啟動成功!
也就是說我們通過entrypoint ["/docker-entrypoint.sh"]
指定的命令在啟動時無論如何都會執行,并且可以接收到了docker run 的參數。
docker-entrypoint.sh是什么?docker-entrypoint.sh這是一個預處理腳本通常用來過濾命令行參數或者執行exec 來啟動容器為1的進程。
通過entrypoint+cmd實現命令默認參數或接收docker run 參數是一種非常流行并且有用的dockerfile編寫方式。
到此這篇關于dockerfile中entrypoint與cmd的結合的文章就介紹到這了,更多相關dockerfile中entrypoint與cmd內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://www.cnblogs.com/qsing/p/15174705.html