RUN、CMD 和 ENTRYPOINT 这三个 Dockerfile 指令看上去很类似,很容易混淆。本节将通过实践详细讨论它们的区别。

简单的说:

  1. RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包。

  2. CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run 后面跟的命令行参数替换。

  3. ENTRYPOINT 配置容器启动时运行的命令。

下面我们详细分析。

Shell 和 Exec 格式

我们可用两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式,二者在使用上有细微的区别。

Shell 格式

<instruction> <command>

例如:

RUN apt-get install python3

CMD echo "Hello world"

ENTRYPOINT echo "Hello world"

当指令执行时,shell 格式底层会调用 /bin/sh -c <command>。

例如下面的 Dockerfile 片段:

ENV name Cloud Man

ENTRYPOINT echo "Hello, $name"

执行 docker run <image> 将输出:

Hello, Cloud Man

注意环境变量 name 已经被值 Cloud Man 替换。

下面来看 Exec 格式。

Exec 格式

<instruction> ["executable", "param1", "param2", ...]

例如:

RUN ["apt-get", "install", "python3"]

CMD ["/bin/echo", "Hello world"]

ENTRYPOINT ["/bin/echo", "Hello world"]

当指令执行时,会直接调用 <command>,不会被 shell 解析。

例如下面的 Dockerfile 片段:

ENV name Cloud Man

ENTRYPOINT ["/bin/echo", "Hello, $name"]

运行容器将输出:

Hello, $name

注意环境变量“name”没有被替换。
如果希望使用环境变量,照如下修改

ENV name Cloud Man

ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]

运行容器将输出:

Hello, Cloud Man

CMD 和 ENTRYPOINT 推荐使用 Exec 格式,因为指令可读性更强,更容易理解。RUN 则两种格式都可以。

RUN

RUN 指令通常用于安装应用和软件包。

RUN 在当前镜像的顶部执行命令,并通过创建新的镜像层。Dockerfile 中常常包含多个 RUN 指令。

RUN 有两种格式:

  1. Shell 格式:RUN

  2. Exec 格式:RUN ["executable", "param1", "param2"]

下面是使用 RUN 安装多个包的例子:

RUN apt-get update && apt-get install -y \

bzr \

cvs \

git \

mercurial \

subversion

注意:apt-get update 和 apt-get install 被放在一个 RUN 指令中执行,这样能够保证每次安装的是最新的包。如果 apt-get install 在单独的 RUN 中执行,则会使用 apt-get update 创建的镜像层,而这一层可能是很久以前缓存的。

CMD

CMD 指令允许用户指定容器的默认执行的命令。

此命令会在容器启动且 docker run 没有指定其他命令时运行。

  1. 如果 docker run 指定了其他命令,CMD 指定的默认命令将被忽略。

  2. 如果 Dockerfile 中有多个 CMD 指令,只有最后一个 CMD 有效。

CMD 有三种格式:

  1. Exec 格式:CMD ["executable","param1","param2"]
    这是 CMD 的推荐格式。

  2. CMD ["param1","param2"] 为 ENTRYPOINT 提供额外的参数,此时 ENTRYPOINT 必须使用 Exec 格式。

  3. Shell 格式:CMD command param1 param2

Exec 和 Shell 格式前面已经介绍过了。
第二种格式 CMD ["param1","param2"] 要与 Exec 格式 的 ENTRYPOINT 指令配合使用,其用途是为 ENTRYPOINT 设置默认的参数。我们将在后面讨论 ENTRYPOINT 时举例说明。

下面看看 CMD 是如何工作的。Dockerfile 片段如下:

CMD echo "Hello world"

运行容器 docker run -it [image] 将输出:

Hello world

但当后面加上一个命令,比如 docker run -it [image] /bin/bash,CMD 会被忽略掉,命令 bash 将被执行:

root@10a32dc7d3d3:/#

ENTRYPOINT

ENTRYPOINT 指令可让容器以应用程序或者服务的形式运行。

ENTRYPOINT 看上去与 CMD 很像,它们都可以指定要执行的命令及其参数。不同的地方在于 ENTRYPOINT 不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令。

ENTRYPOINT 有两种格式:

  1. Exec 格式:ENTRYPOINT ["executable", "param1", "param2"] 这是 ENTRYPOINT 的推荐格式。

  2. Shell 格式:ENTRYPOINT command param1 param2

在为 ENTRYPOINT 选择格式时必须小心,因为这两种格式的效果差别很大。

Exec 格式

ENTRYPOINT 的 Exec 格式用于设置要执行的命令及其参数,同时可通过 CMD 提供额外的参数。

ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器启动时动态替换掉。

比如下面的 Dockerfile 片段:

ENTRYPOINT ["/bin/echo", "Hello"]

CMD ["world"]

当容器通过 docker run -it [image] 启动时,输出为:

Hello world

而如果通过 docker run -it [image] CloudMan 启动,则输出为:

Hello CloudMan

Shell 格式

ENTRYPOINT 的 Shell 格式会忽略任何 CMD 或 docker run 提供的参数。

最佳实践

  1. 使用 RUN 指令安装应用和软件包,构建镜像。

  2. 如果 Docker 镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。

  3. 如果想为容器设置默认的启动命令,可使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。

到这里,我们已经具备编写 Dockerfile 的能力了。如果大家还觉得没把握,推荐一个快速掌握 Dockerfile 的方法:去 Docker Hub 上参考那些官方镜像的 Dockerfile

15-RUN vs CMD vs ENTRYPOINT的更多相关文章

  1. RUN vs CMD vs ENTRYPOINT - 每天5分钟玩转 Docker 容器技术(17)

    RUN.CMD 和 ENTRYPOINT 这三个 Dockerfile 指令看上去很类似,很容易混淆.本节将通过实践详细讨论它们的区别. 简单的说: RUN 执行命令并创建新的镜像层,RUN 经常用于 ...

  2. 第 3 章 镜像 - 017 - RUN vs CMD vs ENTRYPOINT

    RUN.CMD 和 ENTRYPOINT 这三个 Dockerfile 指令看上去很类似,很容易混淆. 简单的说: RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包. CMD 设置容器启动 ...

  3. RUN vs CMD vs ENTRYPOINT

    参考:https://www.ibm.com/developerworks/community/blogs/132cfa78-44b0-4376-85d0-d3096cd30d3f/entry/RUN ...

  4. 017、RUN、CMD、ENTRYPOINT (2019-01-08 周二)

    参考https://www.cnblogs.com/CloudMan6/p/6875834.html   RUN CMD ENTRYPOINT 这三个Dockerfile指令看上去很类似,很容易混淆. ...

  5. docker 15 dockerfile案例-CMD、ENTRYPOINT案例

    CMD.ENTRYPOINT都是指定一个容器启动时要运行的命令.但是CMD会覆盖前面的参数,而ENTRYP会追加组合原来的参数 未完待续...

  6. Dockerfile创建自定义Docker镜像以及CMD与ENTRYPOINT指令的比较

    1.概述 创建Docker镜像的方式有三种 docker commit命令:由容器生成镜像: Dockerfile文件+docker build命令: 从本地文件系统导入:OpenVZ的模板. 关于这 ...

  7. Docker系列(23)- CMD和ENTRYPOINT的区别

    CMD和ENTRYPOINT的区别 CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令 测试CMD ...

  8. 论docker中 CMD 与 ENTRYPOINT 的区别

    Dockerfile里有 CMD 与 ENTRYPOINT 两个功能咋看起来很相似的指令,开始的时候觉得两个互用没什么所谓,但其实并非如此: CMD指令: The main purpose of a ...

  9. 论docker中 CMD 与 ENTRYPOINT 的区别(转)

    Dockerfile 用于自动化构建一个docker镜像.Dockerfile里有 CMD 与 ENTRYPOINT 两个功能咋看起来很相似的指令,开始的时候觉得两个互用没什么所谓,但其实并非如此: ...

随机推荐

  1. 遇见C++ Lambda

    转自:https://www.cnblogs.com/allenlooplee/archive/2012/07/03/2574119.html 遇见C++ Lambda Written by Alle ...

  2. [CSS]关于z-index与position的一次奇异经历

    前言: 前不久,同事S遇到了一个关于position和z-index的问题. 他折腾了一天没搞定,群发了邮件寻求帮助, 我一开始以为很简单,就主动说帮忙,简单尝试之后,才发现貌似没那么简单. 问题主要 ...

  3. 工作中碰到的一个问题(cookie相关)

    今天上线了一个API,6台机器做的集群.API的第一步是读取cookie,判断用户是否登录. 例如,线上服务器分别是 10.255.242.1 10.255.242.2 10.255.242.3 10 ...

  4. 【整理】close 和 shutdown 的原理

    http://stackoverflow.com/questions/14740852/linux-socket-close-vs-shutdown shutdown(sd, SHUT_WR)  发送 ...

  5. JavaScript验证字符串只能包含数字或者英文字符的代码实例

    验证字符串只能包含数字或者英文字符的代码实例:本章节分享一段代码实例,它实现了验证字符串内容是否只包含英文字符或者数字.代码实例如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

  6. vue 项目项目启动时由于EsLint代码校验报错

    今天在编写好vue项目代码时,在命令行输入npm start的时候出现了如下图所示的一大堆错误: 在网上查找资料说是缺少EsLint配置文件的问题,最终找到一篇由 hahazexia 编写的一篇博客文 ...

  7. bitMap算法实现以及ckHash函数类,将字符串映射成数字,同时可以将数字映射成字符串

    ckHash函数类,将字符串映射成数字,同时可以将数字映射成字符串 说明 1.所谓的BitMap就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来 ...

  8. Sequelize-nodejs-6-Instances

    Instances实例 Building a non-persistent instance构建非持久性实例 In order to create instances of defined class ...

  9. 打开一个网站中的不同页面时,相同的js文件会被重复加载吗?

    作者:JasonYang链接:https://www.zhihu.com/question/41184156/answer/135195798来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非 ...

  10. Sublime Text常用设置之个人配置

    一.安装 1.安装包下载:  http://www.sublimetext.com/3 (傻瓜式安装) 2.Package Control安装: 1)Ctrl+~或者View——Show Consol ...