RUN、CMD 和 ENTRYPOINT 这三个 Dockerfile 指令看上去很类似,很容易混淆。

简单的说:

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

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

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 xxx
ENTRYPOINT echo "Hello, $name"

执行 docker run <image> 将输出:

Hello, xxx

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

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 xxx
ENTRYPOINT ["/bin/echo", "Hello, $name"] 

运行容器将输出:

Hello, $name

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

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

运行容器将输出:

Hello, xxx

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 没有指定其他命令时运行。

  • 如果 docker run 指定了其他命令,CMD 指定的默认命令将被忽略。
  • 如果 Dockerfile 中有多个 CMD 指令,只有最后一个 CMD 有效。

CMD 有三种格式:

  1. Exec 格式(推荐):CMD ["executable","param1","param2"]
  2. CMD ["param1","param2"] 为 ENTRYPOINT 提供额外的参数,此时 ENTRYPOINT 必须使用 Exec 格式。
  3. Shell 格式:CMD command param1 param2

举个栗子:

 root@ubuntu:~/# cat Dockerfile
FROM ubuntu
CMD echo "hello world"
root@ubuntu:~/#
root@ubuntu:~/# docker build -t cmd-eg-v1 .
Sending build context to Docker daemon .048kB
Step / : FROM ubuntu
---> 1d9c17228a9e
Step / : CMD echo "hello world"
---> Running in 73a418109975
Removing intermediate container 73a418109975
---> 44b793b3959c
Successfully built 44b793b3959c
Successfully tagged cmd-eg-v1:latest
root@ubuntu:~/#
root@ubuntu:~/# docker run -it cmd-eg-v1
hello world
root@ubuntu:~/# docker run -it cmd-eg-v1 /bin/bash
root@57afa1edf189:/#

在执行 docker run -it [image] /bin/bash,CMD 会被忽略掉,命令 bash 被执行。

ENTRYPOINT

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

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

ENTRYPOINT 有两种格式:

  1. Exec 格式(推荐):ENTRYPOINT ["executable", "param1", "param2"]
  2. Shell 格式:ENTRYPOINT command param1 param2

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

Exec 格式

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

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

举个例子:

 root@ubuntu:~/# cat Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"]
root@ubuntu:~/#
root@ubuntu:~/# docker build -t cmd-eg-v2 .
Sending build context to Docker daemon .048kB
Step / : FROM ubuntu
---> 1d9c17228a9e
Step / : ENTRYPOINT ["/bin/echo", "Hello"]
---> Running in fae6feb9277a
Removing intermediate container fae6feb9277a
---> 93c655c722d2
Step / : CMD ["world"]
---> Running in 0de0893f9c13
Removing intermediate container 0de0893f9c13
---> 3632ca1d41fa
Successfully built 3632ca1d41fa
Successfully tagged cmd-eg-v2:latest
root@ubuntu:~/#
root@ubuntu:~/# docker run -it cmd-eg-v2
Hello world
root@ubuntu:~/# docker run -it cmd-eg-v2 xxx
Hello xxx
root@ubuntu:~/#

Shell 格式

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

小结

  1. 使用 RUN 指令安装应用和软件包,构建镜像。
  2. 如果 Docker 镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。
  3. 如果想为容器设置默认的启动命令,可使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。

---------------------------引用来自-----------------------------------

https://mp.weixin.qq.com/s?__biz=MzIwMTM5MjUwMg==&mid=2653587614&idx=1&sn=2070e193da6b71861052e393eccae055&chksm=8d308087ba4709915514e06e73bba8a93fca5510f910552a8290e9a1b4ae111d7a3fd230c0a5&scene=21#wechat_redirect

第 3 章 镜像 - 017 - RUN vs CMD vs ENTRYPOINT的更多相关文章

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

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

  2. RUN vs CMD vs ENTRYPOINT

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

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

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

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

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

  5. 15-RUN vs CMD vs ENTRYPOINT

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

  6. Dockerfile的 RUN和CMD

    在创建Dockerfile的时候,RUN和CMD都是很重要的命令.它们各自的作用分别如下: RUNRUN命令是创建Docker镜像(image)的步骤,RUN命令对Docker容器( containe ...

  7. Docker | dockerfile构建centos镜像,以及CMD和ENTRYPOINT的区别

    构建自己的centos镜像 docker pull centos下载下来的镜像都是基础版本,缺少很多常用的命令功能,比如:ll.vim等等, 下面介绍制作一个功能较全的自己的centos镜像. 步骤 ...

  8. 论docker中 CMD 与 ENTRYPOINT 的区别

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

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

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

随机推荐

  1. axure rp 8.0注册码(亲测)

    今天在看一需求原型时,发现其他部门发过来是8.0版的,老的7不能用,找了个亲测可用的验证码. License:米 业成 (STUDENT)Key:nFmqBBvEqdvbiUjy8NZiyWiRSg3 ...

  2. 02:MongoDB操作

    1.1 MongoDB 增加 1.插入数据 1. 插入文档: insert 如果插入数据的时候,collection还不存在,自动创建集合 2. insertOne: 插入一条数据 3. insert ...

  3. Junit中AssertTrue的使用

    assertTrue public static void assertTrue(String message, boolean condition) Asserts that a condition ...

  4. Ajax详细剖析

    概述 对于WEB应用程序:用户浏览器发送请求,服务器接收并处理请求,然后返回结果,往往返回就是字符串(HTML),浏览器将字符串(HTML)渲染并显示浏览器上. 传统的Web应用 一个简单操作需要重新 ...

  5. php高级开发参考地址

    高级开发 : http://www.cnblogs.com/bananaplan/p/The-Right-Way-For-PHPer.html

  6. FJUT seventh的tired树上路径(01字典树)题解

    思路(来自题解): 众所周知树上两个点xy的距离是deep[x]+deep[y]-deep[lca(x,y)]*2 然后我们把这个加减法换成异或,我们就会发现,deep[lca(x,y)]被消掉了 所 ...

  7. (转) AdversarialNetsPapers

      本文转自:https://github.com/zhangqianhui/AdversarialNetsPapers AdversarialNetsPapers The classical Pap ...

  8. Component 父子组件关系

    我们把组件编写的代码放到构造器外部或者说单独文件 我们需要先声明一个对象,对象里就是组件的内容. var zdy = { template:`<div>Panda from China!& ...

  9. mybatis配置文件resultMap标签的使用

    本文为博主原创,未经允许不得转载: resultMap标签是为了映射select查询出来结果的集合,其主要作用是将实体类中的字段与 数据库表中的字段进行关联映射. 注意:当实体类中的字段与数据库表中的 ...

  10. [转载]grep查看上下文及简单正则表达式

    转载自:https://www.cnblogs.com/mfryf/p/3336288.html inux grep 显示前后几行的信息2016年03月02日 14:10:58 ChenHui246 ...