首页 > 其他分享 >Dockerfile 中的 CMD 与 ENTRYPOINT

Dockerfile 中的 CMD 与 ENTRYPOINT

时间:2023-10-10 16:37:46浏览次数:64  
标签:00 CMD nginx ENTRYPOINT 参数 docker Dockerfile

1、概述

CMD 和 ENTRYPOINT 指令都用于定义容器启动时执行的命令,单从功能上来看,这两个命令几乎是重复的,单独使用其中的一个就可以实现绝大多数的用例。尽管如此,它们在某些情况下具有不同的用途和优势。这篇文章旨在澄清它们的用法,以帮助你在实际应用中做出明智的选择,避免混淆。

2、介绍

2.1 CMD 指令

CMD 用于指定容器启动时默认执行的命令及其参数。如果 Dockerfile 中包含多个 CMD 指令,则只有最后一个会生效。如果在运行容器时提供了命令参数,它们将覆盖 CMD 中定义的默认命令。

CMD 可以有三种形式:
  • CMD ["executable","param1","param2"](exec 形式,推荐使用,不会通过 shell 执行,更容易处理信号和参数)。
  • CMD command param1 param2(shell 形式,会通过 shell 执行)。
  • CMD ["param1","param2"](作为 ENTRYPOINT 的默认参数)。

2.2 ENTRYPOINT 指令

ENTRYPOINT 用于配置容器启动时执行的命令。如果 Dockerfile 中包含多个 ENTRYPOINT 指令,则只有最后一个会生效。ENTRYPOINT 与 CMD 一起使用时,CMD 的内容会作为参数传递给 ENTRYPOINT 指定的命令。

ENTRYPOINT 可以有两种形式:

  • ENTRYPOINT ["executable", "param1", "param2"](exec 形式,可使用CMD的参数和可使用docker run后面追加的参数)。
  • ENTRYPOINT command param1 param2(shell 形式,不会使用 CMD参数,不可使用docker run后面追加的参数)。

2.3 CMD 与 ENTRYPOINT 的Shell格式和Exec格式

Shell格式:指令 <command>,以 CMD 指令为例。

CMD java -jar test.jar

Exec格式:指令 ["executable", "param1", "param2", ...], 以 CMD 指令为例。

CMD ["nginx", "-g", "daemon off;"]

Shell格式中的命令会直接被Shell解析,Exec格式不会直接解析,需要加参数。

2.4 CMD 与 ENTRYPOINT主要区别

CMD 与 ENTRYPOINT都是用于指定启动容器执行的命令,区别在于:

  • 当docker run 命令中有参数时,守护进程会忽略CMD命令。
  • 使用ENTRYPOINT指令不会忽略,并且会接收docker run 参数附加到命令行中。

为了使构建的容器可以正常启动,我们编写的dockerfile文件必须包含一个CMD或ENTRYPOINT指令(指令在父镜像中的存在也可以)。

3、CMD 与 ENTRYPOINT的结合使用

dockerfile文件中包含多个CMD时,只有最后一个被加载使用。我们在dockerhub中搜索centos官方镜像,看一下的官方dockerfile文件。我们查看latest标签的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"]

只有四行,这就是构建一个latest版本centos8.3.2011镜像的dockerfile全部内容。指定基镜像(这里从scratch这个空镜像开始构建),添加rootfs内容,打标签,通过CMD指定启动命令。
不止centos,其他debian、ubuntu、busybox等镜像都只需通过CMD指定启动命令,比如busybox更为简约。

FROM scratch
ADD busybox.tar.xz /
CMD ["sh"]

这种基础类、工具类镜像的构建我们只需要指定一个必要CMD来启动容器即可。但是我们编写一个dockerfile并不是为了启动容器而编写,大多数时候我们要在容器运行我们的app,运行我们的服务。

当然通过CMD也可以启动,可是如此一来有一个缺陷,我们上面说到的CMD的启动命令会被docker run 参数代替,我们有下面Dockerfile。

FROM centos
CMD ["/bin/top","-b"] 

构建后,使用参数ps启动容器。

[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.1章节我们提到CMD ["param1","param2"]形式可以作为ENTRYPOINT参数,同时ENTRYPOINT 指定的命令无法被docker run 参数取代。假如我们把CMD和ENTRYPOINT两个指令相结合,这样我们就可以通过CMD来接收docker run 参数,然后把参数传递给ENTRYPOINT执行。

我们以nginx官方dockerfile latest版本1.21为例,首先我们查看Dockerfile,这里我们只关注启动命令,如下:

...
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不添加参数时启动容器相当于执行如下脚本与默认参数。

#docker-entrypoint.sh nginx -g "daemon off;"

当我们使用docker run 传入参数会怎样?传入nginx-debug

#docker run -dt nginx nginx-debug -g "daemon off;"

此时启动容器相当于执行如下脚本与参数。

#docker-entrypoint.sh nginx-debug -g "daemon off;"

我们通过ps来看一下我们启动的容器。

# docker run不添加参数
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
# docker run添加参数
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 的参数。

4、总结

通过ENTRYPOINT+CMD实现命令默认参数或接收docker run 参数是一种非常流行并且有用的dockerfile编写方式。

5、其他

参考:本文大部分内容都是参考《dockerfile中ENTRYPOINT与CMD的结合》这篇博文。

优质博文:Dockerfile中CMD与ENTRYPOINT命令的区别

优质博文:Dockerfile 中的 CMD 与 ENTRYPOINT 

标签:00,CMD,nginx,ENTRYPOINT,参数,docker,Dockerfile
From: https://www.cnblogs.com/zhangmingcheng/p/17754949.html

相关文章

  • [900] Print an empty line of CMD batch scripts
    Usetheecho.commandtoprintanemptyline.@echooffechoThisisalineoftextecho.echoThisisanewlineoftextThiswillproducetheoutput:ThisisalineoftextThisisanewlineoftextUsingecho.isacommonmethodforprintingnewline......
  • [901] Reuse variables of CMD batch scripts
    Inabatchfile,youcanreuseavariabletogeneratedifferentfilepathsbyconcatenatingthevariablewithotherstringsorvariables.Here'sanexampleofhowtodothis:@echooffset"base_path=C:\Example"REMGeneratefilepathsus......
  • [902] Get the current file's directory of CMD batch scripts
    Inabatchfile,youcanusethe%~dp0specialvariabletogetthedirectoryofthecurrentlyexecutingbatchfile.Here'showyoucandoit:@echooffechoThedirectoryofthisbatchfileis:%~dp0Whenyourunthisbatchfile,itwilldisplaythe......
  • entity-framework 'scaffold-dbcontext' 未被识别为 cmdlet、函数、脚本文件或可操
    //出现此错scaffold-dbcontext:Theterm'scaffold-dbcontext'isnotrecognizedasthenameofacmdlet,function,scriptfile,oroperableprogram.Checkthespellingofthename,orifapathwasincluded,verifythatthepathiscorrectandtry......
  • [893] Add comments at a batch file (CMD)
    ref:HowdoIdocommentsataWindowscommandprompt?REM isthestandardway:REMthisisacommentYoucouldalsousethedouble-colonconventioncommonlyseeninbatchfiles:::anothercommentAsinglecolonfollowedbyastringisalabel,buta......
  • DockerFile部署wordpress并制作成镜像实践
    目录DockerFile部署wordpress实践部署wordpress准备Dockerfile所需文件开始制作成镜像访问网页将wordpress打包成镜像DockerFile部署wordpress实践部署wordpress#创建dockerfile目录[root@docker02~]#mkdir/Dockerfile#进入dockerfile目录[root@docker02......
  • cmd输入mysql不是内部或外部指
    如果在cmd中输入mysql后出现“mysql不是内部或外部指令”,那么可能是以下几个问题导致的。1.没有正确安装MySQL第一步,到MySQL官网下载安装程序;第二步,在安装程序中选择完全安装,确保包括MySQL的bin目录(默认路径为C:\ProgramFiles\MySQL\MySQLServer5.7\bin)被加......
  • 利用CMD窗口查看app数据库的内容
    利用CMD窗口查看app数据库的内容一般app的数据存储都在/data/data/目录下adbshell-xcddata/data/ls(查看相关文件夹内容)cdcom.xxx.xxxxxx(一般都是app的包名)sqlite3BT.db(数据库名字)利用sql语法查看数据库表中的内容,例如:select*fromstudent;......
  • Dockerfile构建镜像
    使用Dockerfile文件可以构建镜像,通过镜像可以运行多个实例,镜像是静态的,而容器是根据镜像生成的,活动在内存中。我们来学习一下如何来写Dockerfile文件我们需要新建一个文件夹,在文件夹内生成一个Dockerfile文件(Dockerfile文件名是规范首字母必须大写,其余为小写),和构建镜像需要的in......
  • cmd powershell 命令行窗口保存更多的历史记录输出行数,防止上面的输出被自动删除
    布局-屏幕缓冲区大小-高度调大或者是用https://stackoverflow.com/questions/71099275/can-view-the-history-of-powershell-outputs这个办法自动保存到一个txt文件中参考https://stackoverflow.com/questions/1740876/more-lines-in-command-window ......