Docker 中 RUN、CMD 与 ENTRYPOINT 的区别_docker run cmd-程序员宅基地

技术标签: 云原生  容器  运维  docker  

前言

在说 CMD、RUN 和 ENTRYPOINT 的区别前,先来说说 Dockerfile,Dockerfile 是构建容器镜像的方式之一,其通过一系列的指令参数来完成镜像的构建,而这些参数正是包含了 CMD,、RUN、COPY、ADD 和 ENTRYPOINT 等一系列指令。因此在实际应用中我们更多都是通过 Dockerfile 来完成镜像的构建。接下来列举一些 Dockerfile 常用的指令。

一、Dockerfile 常用指令

  • FROM

    指定基础(base)镜像,本地有镜像则直接使用,否则直接在线拉取(pull)。

  • MAINTAINER

    Author,对作者的简单描述,自定义。

  • COPY

    将文件或目录从 build context 复制到镜像,其支持两种格式:COPY src dest 和 COPY[“src”,“dest”]

    注:原目标(src)只能是文件或目录。

  • ADD

    与 COPY 类似,复制文件到镜像,不同的是,ADD 的 src 是归档文件(tar、zip、tgz 等),这些归档文件会被自动解压到 dest (镜像目标路径),无需手动解压。

  • ENV

    设置环境变量,该变量可被后面的指令使用。

  • EXPOSE

    指定容器中的进程会监听的某个端口,指定后 Docker 可以将该端口暴露出来。

  • VOLUME

    将文件或目录声明为 volume,同样 Docker 可以将该目录或文件映射出来。

  • WORKDIR

    为后面的 RUN、CMD、ENTRYPOINT、ADD、COPY 指令设置镜像中的当前工作目录。

  • RUN

    在容器中运行指令的命令。

  • CMD

    启动容器时运行指定的命令,Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,如果 docker run 后面指定有参数,该参数将会替换 CMD 的参数。

  • ENTRYPOINT

    同样,在 Dockerfile 中可以有多个 ENTRYPOINT 指令,也是只有最后一个生效,但与 CMD 不同的是,CMD 或 docker run 之后的参数会被当作参数传给 ENTRYPOINT。

二、三者的区别

2.1 Shell 和 Exec 格式

通常,我们有两种方式来指定 RUN、CMD 和 ENTRYPOINT 要运行的命令,即 Shell 和 Exec 方式。CMD 和 ENTRYPOINT 推荐使用 Exec 格式,其可读性更强。

1、Shell 格式

RUN yum install -y vim
CMD echo "hello zhurs"
ENTRYPOINT echo "hello zhurs"

# 运行容器时返回如下结果
hello zhurs

当指令执行时,Shell 格式会调用 /bin/sh -c [command]

2、Exec 格式

[“executable”, “param1”, “param2”]

RUN ["yum", "install", "-y", "vim"]
CMD ["bin/echo", "zhurs"]
ENV wd world
ENTRYPOINT ["/bin/echo", "hello, $wd"]

# 运行容器时返回如下结果
hello $wd

# 可看到运行容器时并没有调用/bin/sh -c 没有被shell解析(环境变量wd并没有被替换)。

# 如果希望使用环境变量,可做如下操作
RUN ["yum", "install", "-y", "vim"]
CMD ["bin/echo", "zhurs"]
ENV wd world
ENTRYPOINT ["bin/sh", "-c", "/bin/echo", "hello, $wd"]

# 此时就会返回如下结果
hello world

2.2 RUN

RUN 指令通常用于安装应用和软件包,每条 RUN 指令都会生成新的镜像。

...
RUN apt update && apt install -y git
...

像在安装一些基础工具或应用的时候,apt update 和 apt install … 最好放在一个 RUN 指令下执行,因为这能够保证每次安装的是最新的包,如果 apt update 在单独的 RUN 下运行,则 apt install … 会使用 apt update 创建的镜像,而这一层镜像可能是很久以前缓存的镜像文件。

2.3 CMD

该指令用于用户启动容器时,容器来执行的命令,该命令会在容器启动且 docker run 后面没有指定其他命令时执行,所以小结三种情况:

  • docker run 没指定其他命令:则启动容器时运行 CMD 后的命令;
  • docker run 指定了其他命令:则启动容器时运行 CMD 后的命令会被忽略;
  • Dockerfile 中有多条 CMD 指令时,仅最后一条生效。

CMD 的三种格式:

  • shell 格式:CMD <二进制可执行命令> <指令1> <指令2> 如:CMD yum install -y vim
  • exec 格式:CMD [“二进制可执行命令”, “指令1”, “指令2”] 如:RUN [“yum”, “install”, “-y”, “net-tools”]
  • CMD [“a”,“b”] 格式:该格式是为 ENTRYPOINT 提供使用,此时 ENTRYPOINT 就必须使用 exec 格式,否则不生效。

2.4 ENTRYPOINT

该指令可以让容器以应用程序或者服务的形式运行。与 CMD 不同的是,不管 docker run … 后是否运行有其他命令,ENTRYPOINT 指令后的命令一定会被执行。

ENTRYPOINT 的两种格式:

  • shell 格式:同 CMD;
  • exec 格式:同 CMD。

ENTRYPOINT 的 exec 格式可以可执行由 CMD 提供的额外参数,具体如下:

...
ENTRYPOINT ["/bin/echo", "hello"] CMD ["world"]
...

运行容器时:

  • docker run -it

    运行的容器后无任何参数

    # 输出
    hello world
    
  • docker run -it myworld

    运行的容器后跟了 myworld 参数

    # 输出
    hello myworld
    

ENTRYPOINT 小结:

无论运行的容器命令后是否有其他参数,ENTRYPOINT 一律执行,如果 ENTRYPOINT 后跟随有 CMD 指令参数,则该参数的内容将会作为 ENTRYPOINT 指令参数。如果 docker run ... 后有参数,ENTRYPOINT 则使用该参数,而不会使用 CMD 的参数,为什么呢?因为 docker run ... 后指定了参数,那么根据前面说到的 CMD 后的参数将会被忽略掉(或叫被替换)。

但是上面的结论是针对 ENTRYPOINT 的 exec 格式而言的,如果是 shell 格式,ENTRYPOINT 将会忽略掉任何 CMD 或 docker run … 提供的参数。当然 ENTRYPOINT 的 shell 格式也是会必然执行的。

2.5 如何选择 CMD 和 ENTRYPOINT

根运行容器的属性来合理选择

  • 如果运行的是一个 MySQL 容器,则优先使用 exec 格式的 ENTRYPOINT 指令,因为 CMD 不仅可以为 ENTRYPOINT 提供默认参数,同时在 docker run ...(带参数)的时候,该参数也会替换 CMD 默认参数。
  • 如果只是简单的设置容器默认的启动命令,使用 CMD 即可,用户只需在 docker run ... 后添加参数即可替换默认值。

小结

  • RUN:执行命令并创建新的镜像层,常用于安装软件包;
  • CMD:设置容器启动后默认执行的命令及其参数,但 docker run 后跟参数时会替换(忽略) CMD;
  • ENTRYPOINT:配置容器启动时运行的命令。

<点击跳转至开头>

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/IT_ZRS/article/details/124707747

智能推荐

一文总结十大经典排序算法(思维导图 + 动图演示 + 代码实现 C/C++/Python + 致命吐槽)_排序算法思维导图-程序员宅基地

文章浏览阅读1.2w次,点赞86次,收藏587次。冒泡排序void Swap( ElementType *a, ElementType *b ){ ElementType t = *a; *a = *b; *b = t;}void BubbleSort(ElementType A[], int N){ int P,i; int flag; for(P=N-1;P>=0;P--){ flag=0; for(i=0..._排序算法思维导图

webpack插件_while resolving: [email protected]程序员宅基地

文章浏览阅读361次。add-asset-html-webpack-plugin将JavaScript或CSS资产添加到生成的HTML中 html-webpack-pluginbabel-coreBabel编译器核心。babel-loader该软件包允许使用Babel和webpack转换JavaScript文件。babel-plugin-syntax-dynamic-impor语法动态导入babel-p..._while resolving: [email protected]

jsonString 常用方法_josnstring-程序员宅基地

文章浏览阅读1.2k次。1. Map 转Json Stringimport com.google.gson.Gson;Map<String,Integer> indicatorDetails = new HashMap<>();Gson gson = new Gson();String jsonStr = gson.toJson(indicatorDetails);2...._josnstring

ios发布App遇到的问题:“*证书*”has one iOS Distribution certificate but its private key is not installed_has one ios distribution but its private key is no-程序员宅基地

文章浏览阅读1.1k次。解决方法:重新创建certificate证书,上传本机的CSR证书认证文件3.Production(一般只能创建3次)选中:App Store and Ad Hoc 然后下载证书到桌面,双击安装后,重新发布app到App Store中即可 转载自:https://blog.csdn.net/yishengzhiai005/article/details/7863..._has one ios distribution but its private key is not installed

Houdini VEX 学习笔记 (二)-程序员宅基地

文章浏览阅读1.1k次。//利用属性分开PrimitivePrimitive Split 节点中Attribute 设置为split 。Wrangle中代码为: f@split = @ptnum>10?1:4; 比较程序化的是利用Houdini 的Paint 节点,给物体描绘上颜色,然后利用颜色属性把Primitive 分开//曲线(在Vex中实现Carve节点的功能)最近在做植物生长的r..._houdini adjustprimlength

Qt+OSG/osgEarth跨平台编译(用Qt Creator组装各个库,实现一套代码、一套框架,跨平台编译)_qt osgearth-程序员宅基地

文章浏览阅读5.6k次,点赞9次,收藏46次。Qt+OSG/osgEarth跨平台编译(Windows、linux、macos)。用Qt Creator组装各个库,实现一套代码、一套框架,完成跨平台编译第三方库;实现一套代码、一套框架,完成跨平台编译OSG核心库、工具库、插件库及内省库,osgEarth核心库及插件库。_qt osgearth

随便推点

关于python中numpy生成随机数的那点事_numpy 让数组内色数据随机浮动-程序员宅基地

文章浏览阅读611次。python 中 numpy 是一个非常实用的工具包,它的底层由 c 编写,效率快于原生的 python。本文将主要介绍 python 产生随机数的主流方法,有一定的可视化图片,通俗易通理解他们的用法。_numpy 让数组内色数据随机浮动

手动安装python包遇到error:could not find suitable distribution for Requirement.parse(‘certifi>=2017.4.17‘)-程序员宅基地

文章浏览阅读1.2w次,点赞6次,收藏5次。前天执行脚本时调用了一个requests库,把脚本放到了linux系统里跑了一下,提示找不到该库。那简单啊,pip下载不就好了!pip install requests啊哦 出错了在经历了多轮百度后。。。没什么效果,排查了一圈dns,代理,下载源,发现可能是我的网络有问题。没办法了,只能手动了先去网站上把我需要的包下下来,https://pypi.org/project/requests,下载完成,解压后放在python安装目录sitepackages下,执行python setup.py i_could not find suitable distribution for requirement.paser(pynacl)

深度学习之经典神经网络框架详解(四):ResNet-v1残差神经网络_resnetv1-程序员宅基地

文章浏览阅读3.3k次,点赞2次,收藏10次。Deep Residual Learning for Image Recognition简述:残差神经网络在2015年ILSVRC比赛中获得冠军,且多个方面获得了第一名。随着网络深度的增加,梯度在反向传播过程中会逐渐消失,导致无法对前面的网络层的权重进行有效的调整,致使准确率逐渐饱和然后迅速下降。本文提出了一个残差学习框架来简化网络训练,实验表明该网络更易优化,且大幅增加深度的同时获得高的精度..._resnetv1

使用C++实现LR(0)语法分析器的操作_c++lr0-程序员宅基地

文章浏览阅读1.2w次,点赞16次,收藏99次。使用C++ 完成LR(0)的语法分析器由于最近学校里在学习编译原理,而且要求实现语法分析器,于是我用了几天的时间搞明白了语法分析器的原理并且将其实现了。由于编者还是本科生而且还在学习中,因此出现什么错误请各位指点。语法分析器的步骤为:读入单词序列读入语法规则构造基于该语法的Clousure(项目集规范族)集合基于上一步构造所有规范句型活前缀的DFA根据这个DFA来构造Action表..._c++lr0

Odoo XML中操作记录与函数-程序员宅基地

文章浏览阅读570次。转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826037.html一:XML文件中定义记录 XML中定义记录: 每个<record>元素有两个基本属性id和model,并且包含为每列分配值的<field>元素。如前所述,id属性对应于记录的外部标识符,模型属性对应于要写入..._odoo xml调用后台函数

LTE技术简介_lte标准-程序员宅基地

文章浏览阅读3.3w次,点赞3次,收藏41次。我们知道,LTE是一个和WCDMA、GSM类似的术语,指的是移动通信的一种技术体系。不过和WCDMA、GSM的命名方式又不太一样,从WCDMA我们可以看出所采用的关键技术,从GSM我们可以看到应用场合,从LTE的命名中,似乎看不出技术特点和应用场合,是一种玄妙的命名方式。一说到LTE,就会想到4G。移动通信技术经历了1G、2G、3G、4G,到现在的5G,分别表示的是第一、二、三、四、五代移动通信系统,每一代都有各自的主流移动通信技术。目前,GSM和WCDMA可以当之无愧地称为2G和3G的主流移动通信技术。_lte标准