当前位置:首页 » 《资源分享》 » 正文

Dockerfile中的RUN、CMD、ENTRYPOINT的区别详解

2 人参与  2024年10月28日 16:40  分类 : 《资源分享》  评论

点击全文阅读


我们在构建Docker镜像的时候,可以通过定义Dockerfile文件的方式,文件中包含了一系列命令参数,而这些参数正是包含了 CMD,、RUN、COPY、ADD 和 ENTRYPOINT 等一系列指令。这篇文章我们一起来学习下其中RUN、CMD、ENTRYPOINT三个命令参数的作用及区别。文章涉及到实际操作,截图多,篇幅长,可以直接跳转到最后看总结了解。

Shell 和 Exec命令格式

无论是RUN、CMD还是ENTRYPOINT运行的命令,都可以Shell或者Exec格式的,两者有一定的区别。总的来说,Shell格式的命令,在底层调用时,会在命令前加上/bin/sh ,那么命令中的用$修饰的参数会被替换;而Exec格式的命令,更像是字符串数组类型,如果自己没有添加/bin ,就不会进行参数替换。话不多说,看例子。

先创建一个空目录,目录中新建一个Dockerfile文件,文件内容如下:

FROM ubuntu:latestENV name UltramanRUN echo "RUN shell Hello $name!"#CMD echo "CMD shell Hello $name!"#ENTRYPOINT echo "ENTRYPOINT shell Hello $name!"#RUN ["echo","RUN exec Hello $name!"]#CMD ["echo","CMD exec Hello $name!"]#ENTRYPOINT ["echo", "ENTRYPOINT exec Hello $name!"]

注意这里#是注释,方便一条一条命令做演示调试。
Dockerfile

Shell

这里我们用RUN命令来做演示。接着我们根据此Dockerfile来构建镜像。

在这里插入图片描述

RUN命令其实是在构建镜像的时候会被执行,看图中框起来的部分可以看到RUN命令被正确执行,并且name参数也成功替换了。这是Shell方式,我们再来看看Exec方式。

Exec

在这里插入图片描述
修改Dockerfile文件,并且构建,可以看到构建过程中有打印,但是name变量没有被正确替换,如果想要使用Exec格式,需要修改下命令,例如:
在这里插入图片描述

RUN

我们在了解了两种命令格式之后,来看下三个命令的使用及区别。
RUN命令是在构建镜像的时候被执行的,所以一般用来安装应用和软件包,一个Dockerfile中可以包含多个RUN命令来安装多个应用或者软件包。另外,我们知道Docker的镜像常常是由多个镜像层layer组成的,一个RUN命令就会在镜像的顶部可写层创建一个新的镜像层。

例如:

RUN yum update && yum install -y \   bzr \ cvs

注意 通常我们把yun update 和 yum install 命令会放在一个RUN指令中一起执行,这样可以保证每次安装的包都是最新版本的。如果我们分开来执行,比如放在两个RUN命令中,那么我们无法保证每次下载的都是最新的包,因为一个RUN命令对于Docker来说会生成一个新的layer层,有可能在之前就已经创建过yum update的层,有缓存。这个在了解了Docker的原理之后会更好的理解。

CMD

CMD命令设置容器启动后默认执行的命令及其参数,但CMD能够被docker run后面跟的命令行参数替换。例如:
我们在Dockerfile中加上一段cmd echo "Hello world",然后docker build成镜像,并且执行docker run -it <imagename>启动一个容器,看到输出
在这里插入图片描述
我们这时候修改启动命令,在启动命令后面加上一个命令,可以看到CMD的内容被覆盖了
在这里插入图片描述
另外,需要注意的是,如果Dockerfile中有多个CMD,那么只会有最后一个生效,如果容器启动时没有指定要执行的命令,那么就会执行最后一个。
在这里插入图片描述

ENTRYPOINT

ENTYRYPOINT命令也可以用来当作启动容器时执行的命令,与CMD不同的是,ENTRYPOINT命令始终会被使用,也不会轻易的被docker启动命令覆盖。可以使用docker run --entrypoint参数覆盖。
举个例子说明:

ENTRYPOINT ["/bin/sh"]CMD ["-c","java $JAVA_OPTS -jar /demo.jar","--server.port=8000"]

很多官方的基础镜像的启动命令都是/bin/bash,容器启动就会进入终端命令行。

两种命令格式:
如果是ENTRYPOINT + [Exec]格式命令,那么CMD的参数会被追加在后面;
如果是ENTRYPOINT + shell格式命令,那么就会忽略CMD以及启动参数,当然此命令依然会被执行。

所以一般ENTRYPOINT用来当作Dockerfile的最后一行,CMD用于指定容器启动时要执行的命令参数,而ENTRYPOINT用于指定容器启动时要执行的可执行文件。可以将ENTRYPOINT看作是容器的默认入口点,而CMD则是对ENTRYPOINT指定的可执行文件的参数进行补充。

最佳实践就是:ENTRYPOINT命令用来定义主命令,CMD命令常用来给ENTRYPOINT命令提供参数。


点击全文阅读


本文链接:http://zhangshiyu.com/post/179090.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1