Dockerfile RUN 、 CMD 、 ENTRYPOINT区别

这些docker指令看起来很类似,容易让刚开始使用docker的开发人员形成混淆。在这篇文章中,我将解释CMD、RUN和ENTRYPOINT之间的区别。python

  • RUN 在新图层中执行命令并建立新图像。例如,它一般用于安装软件包。
  • CMD 设置默认命令和/或参数,当docker容器运行时,能够从命令行覆盖这些命令和/或参数。
  • ENTRYPOINT 配置将做为可执行文件运行的容器。

Docker图像和图层

当Docker运行一个容器时,它会在其中运行一个镜像。此镜像一般经过执行Docker指令构建,该指令在现有镜像或OS分布之上添加层。OS分布是初始图像,每一个添加的层都会建立一个新镜像。git

Shell和Exec形式

全部三个指令(RUN,CMD和ENTRYPOINT)均可以用shell形式或exec形式指定。让咱们首先熟悉这些形式,由于形式一般比指令自己更容易引发混淆。docker

shell形式

<instruction> <command>
复制代码

Examples:shell

RUN apt-get install python3
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"
复制代码

当以shell形式执行指令时,它会调用/bin/sh -c 并进行正常的shell处理。例如,Dockerfile中的如下代码段bash

ENV name John Dow
ENTRYPOINT echo "Hello, $name"
复制代码

当容器运行docker run -it 时将输出ui

Hello, John Dow
复制代码

注意:变量名称将替换为其值。spa

Exec形式

这是CMD和ENTRYPOINT指令的首选形式。命令行

<instruction> ["executable", "param1", "param2", ...]
复制代码

Examples:版本控制

RUN ["apt-get", "install", "python3"]
CMD ["/bin/echo", "Hello world"]
ENTRYPOINT ["/bin/echo", "Hello world"]
复制代码

当以exec形式执行指令时,它直接调用可执行文件,而且不会发生shell处理。例如,Dockerfile中的如下代码段code

ENV name John Dow
ENTRYPOINT ["/bin/echo", "Hello, $name"]
复制代码

当容器运行docker run -it 时将输出

Hello, $name
复制代码

注意:变量名称未替换。

怎么运行bash?

若是你须要运行bash(或任何其余解释器如sh),使用exec形式与/bin/bash做为可执行文件。在这种状况下,将进行正常的shell处理。例如,Dockerfile中的如下代码段

ENV name John Dow
ENTRYPOINT ["/bin/bash", "-c", "echo Hello, $name"]
复制代码

当容器运行docker run -it 时将输出

Hello, John Dow
复制代码

RUN

RUN指令容许您安装应用程序和程序包。它在当前镜像之上执行任何命令,并经过提交结果来建立新层。一般,您会在Dockerfile中找到多个RUN指令。

RUN有两种形式

  • RUN (shell 形式)
  • RUN ["executable", "param1", "param2"] (exec 形式)

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添加的层,这多是好久之前建立的。建议多个指令用&&隔开在一个run中执行。

CMD

CMD指令容许您设置默认命令,该命令仅在您运行容器不指定命令时候运行。若是Docker容器使用命令运行,则将忽略默认命令。若是Dockerfile具备多个CMD指令,则忽略除最后一个CMD指令以外的全部指令。

CMD有三种形式:

  • CMD ["executable","param1","param2"] (exec 形式, 推荐)
  • CMD ["param1","param2"] (以exec形式为ENTRYPOINT设置其余默认参数)
  • CMD command param1 param2 (shell 形式)

第一和第三种形式在Shell和Exec部分进行了解释。第二种exec形式和ENTRYPOINT指令一块儿使用。若是容器在没有命令行参数的状况下运行,它将设置将在ENTRYPOINT参数以后添加的默认参数。参见ENTRYPOINT。

咱们来看看CMD指令是如何工做的。Dockerfile中的如下片断

CMD echo "Hello world" 
复制代码

当容器运行docker run -it 时将输出

Hello world
复制代码

可是当容器使用命令运行时,例如, docker run -it /bin/bash,忽略CMD并改成运行bash指令:

root@7de4bed89922:/#
复制代码

ENTRYPOINT

ENTRYPOINT指令容许您配置将做为可执行文件运行的容器。它看起来相似于CMD,由于它还容许您使用参数指定命令。区别在于当Docker容器使用命令行参数运行时,ENTRYPOINT命令不会忽略参数。(有一种方法能够忽略ENTTRYPOINT,但你不太可能这样作。)

ENTRYPOINT 有两种形式:

  • ENTRYPOINT ["executable", "param1", "param2"] (exec 形式,推荐)
  • ENTRYPOINT command param1 param2 (shell 形式)

选择ENTRYPOINT形式时要很是当心,由于不一样形式执行结果会有很大差别。

Exec 形式

ENTRYPOINT的Exec形式容许您设置命令和参数,而后使用任一形式的CMD来设置更可能更改的其余参数。使用ENTRYPOINT参数,而能够经过Docker容器运行时提供的命令行参数覆盖CMD。例如,Dockerfile中的如下代码段

ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"]
复制代码

当容器运行docker run -it 时将输出

Hello world
复制代码

可是当容器运行docker run -it John时,将输出

Hello John
复制代码

Shell 形式

Shell形式的ENTRYPOINT忽略任何CMD或docker运行命令行参数。

使用RUN指令经过在初始镜像上添加层来构建镜像。

在构建可执行的Docker镜像时,首选ENTRYPOINT的CMD形式。另外若是须要提供额外的默认参数,能够在docker容器运行时从命令行覆盖,请使用CMD。

若是须要提供默认命令和/或在docker容器运行时能够从命令行覆盖的参数,请选择CMD。

相关文章
相关标签/搜索