窗外沥淅的雨 發表於 2016-1-29 23:53:00

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

<h1>1.概述</h1>
<p class="p0">创建<span style="font-family: Times New Roman">Docker</span><span style="font-family: 宋体">镜像的方式有三种</span></p>
<ul>
<li class="p0">docker&nbsp;commit<span style="font-family: 宋体">命令:由容器生成镜像;</span></li>
<li class="p0">Dockerfile<span style="font-family: 宋体">文件</span><span style="font-family: Times New Roman">+docker&nbsp;build</span><span style="font-family: 宋体">命令;</span></li>
<li class="p0">从本地文件系统导入:<span style="font-family: Times New Roman">OpenVZ</span><span style="font-family: 宋体">的模板。</span></li>
</ul>
<p class="p0">关于这三种方式的大致说明请参考yeasy/docker_practice的创建镜像。</p>
<p class="p0">最近学习了<span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">文件的相关配置,这里做一下简单的总结,并对之前一直感到有些迷惑的</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">和</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指令</span>做个差异对比。</p>
<h1>2.Dockerfile文件总结</h1>
<p class="p0">Dockerfile&nbsp;<span style="font-family: 宋体">由一行行命令语句组成,并且支持以&nbsp;</span><span style="font-family: Times New Roman">#&nbsp;</span><span style="font-family: 宋体">开头的注释行。</span></p>
<p class="p0">一般地,Dockerfile&nbsp;<span style="font-family: 宋体">分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。</span></p>
<table>
<tbody>
<tr>
<td valign="top" width="198">
<p class="p0">四部分</p>
</td>
<td valign="top" width="369">
<p class="p0">指令</p>
</td>
</tr>
<tr>
<td valign="top" width="198">
<p class="p0">基础镜像信息</p>
</td>
<td valign="top" width="369">
<p class="p0">FROM</p>
</td>
</tr>
<tr>
<td valign="top" width="198">
<p class="p0">维护者信息</p>
</td>
<td valign="top" width="369">
<p class="p0">MAINTAINER</p>
</td>
</tr>
<tr>
<td valign="top" width="198">
<p class="p0">镜像操作指令</p>
</td>
<td valign="top" width="369">
<p class="p0">RUN<span style="font-family: 宋体">、</span><span style="font-family: Times New Roman">COPY</span><span style="font-family: 宋体">、</span><span style="font-family: Times New Roman">ADD</span><span style="font-family: 宋体">、</span><span style="font-family: Times New Roman">EXPOSE</span><span style="font-family: 宋体">等</span></p>
</td>
</tr>
<tr>
<td valign="top" width="198">
<p class="p0">容器启动时执行指令</p>
</td>
<td valign="top" width="369">
<p class="p0">CMD<span style="font-family: 宋体">、</span><span style="font-family: Times New Roman">ENTRYPOINT</span></p>
</td>
</tr>
</tbody>
</table>
<p class="p0">Dockerfile<span style="font-family: 宋体">文件的第一条指令必须是</span><span style="font-family: Times New Roman">FROM</span><span style="font-family: 宋体">,其后可以是各种镜像的操作指令,最后是</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">或</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指定容器启动时执行的命令。</span></p>
<p class="p0">下面引用yeasy/docker_practice对<span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">中各个指令的介绍,</span></p>
<blockquote>
<p class="p0"><strong>指令</strong></p>
<p class="p0">指令的一般格式为&nbsp;<span style="font-family: Times New Roman">INSTRUCTION&nbsp;arguments<span style="font-family: 宋体">,指令包括&nbsp;<span style="font-family: Times New Roman">FROM<span style="font-family: 宋体">、<span style="font-family: Times New Roman">MAINTAINER<span style="font-family: 宋体">、<span style="font-family: Times New Roman">RUN&nbsp;<span style="font-family: 宋体">等。</span></span></span></span></span></span></span></span></p>
<p class="p0"><strong>FROM</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">FROM&nbsp;&lt;image&gt;<span style="font-family: 宋体">或<span style="font-family: Times New Roman">FROM&nbsp;&lt;image&gt;:&lt;tag&gt;<span style="font-family: 宋体">。</span></span></span></span></p>
<p class="p0">第一条指令必须为&nbsp;<span style="font-family: Times New Roman">FROM&nbsp;<span style="font-family: 宋体">指令。并且,如果在同一个<span style="font-family: Times New Roman">Dockerfile<span style="font-family: 宋体">中创建多个镜像时,可以使用多个&nbsp;<span style="font-family: Times New Roman">FROM&nbsp;<span style="font-family: 宋体">指令(每个镜像一次)。</span></span></span></span></span></span></p>
<p class="p0"><strong>MAINTAINER</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">MAINTAINER&nbsp;&lt;name&gt;<span style="font-family: 宋体">,指定维护者信息。</span></span></p>
<p class="p0"><strong>RUN</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">RUN&nbsp;&lt;command&gt;&nbsp;<span style="font-family: 宋体">或&nbsp;<span style="font-family: Times New Roman">RUN&nbsp;["executable",&nbsp;"param1",&nbsp;"param2"]<span style="font-family: 宋体">。</span></span></span></span></p>
<p class="p0">前者将在&nbsp;<span style="font-family: Times New Roman">shell&nbsp;<span style="font-family: 宋体">终端中运行命令,即&nbsp;<span style="font-family: Times New Roman">/bin/sh&nbsp;-c<span style="font-family: 宋体">;后者则使用&nbsp;<span style="font-family: Times New Roman">exec&nbsp;<span style="font-family: 宋体">执行。指定使用其它终端可以通过第二种方式实现,例如&nbsp;<span style="font-family: Times New Roman">RUN&nbsp;["/bin/bash",&nbsp;"-c",&nbsp;"echo&nbsp;hello"]<span style="font-family: 宋体">。</span></span></span></span></span></span></span></span></p>
<p class="p0">每条&nbsp;<span style="font-family: Times New Roman">RUN&nbsp;<span style="font-family: 宋体">指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用&nbsp;<span style="font-family: Times New Roman">\&nbsp;<span style="font-family: 宋体">来换行。</span></span></span></span></p>
<p class="p0"><strong>CMD</strong></p>
<p class="p0">支持三种格式</p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;CMD&nbsp;["executable","param1","param2"]&nbsp;<span style="font-family: 宋体">使用&nbsp;<span style="font-family: Times New Roman">exec&nbsp;<span style="font-family: 宋体">执行,推荐方式;</span></span></span></p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;CMD&nbsp;command&nbsp;param1&nbsp;param2&nbsp;<span style="font-family: 宋体">在&nbsp;<span style="font-family: Times New Roman">/bin/sh&nbsp;<span style="font-family: 宋体">中执行,提供给需要交互的应用;</span></span></span></p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;CMD&nbsp;["param1","param2"]&nbsp;<span style="font-family: 宋体">提供给&nbsp;<span style="font-family: Times New Roman">ENTRYPOINT&nbsp;<span style="font-family: 宋体">的默认参数;</span></span></span></p>
<p class="p0">指定启动容器时执行的命令,每个&nbsp;<span style="font-family: Times New Roman">Dockerfile&nbsp;<span style="font-family: 宋体">只能有一条&nbsp;<span style="font-family: Times New Roman">CMD&nbsp;<span style="font-family: 宋体">命令。如果指定了多条命令,只有最后一条会被执行。</span></span></span></span></p>
<p class="p0">如果用户启动容器时候指定了运行的命令,则会覆盖掉&nbsp;<span style="font-family: Times New Roman">CMD&nbsp;<span style="font-family: 宋体">指定的命令。</span></span></p>
<p class="p0"><strong>EXPOSE</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">EXPOSE&nbsp;&lt;port&gt;&nbsp;[&lt;port&gt;...]<span style="font-family: 宋体">。</span></span></p>
<p class="p0">告诉&nbsp;<span style="font-family: Times New Roman">Docker&nbsp;<span style="font-family: 宋体">服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过&nbsp;<span style="font-family: Times New Roman">-P<span style="font-family: 宋体">,<span style="font-family: Times New Roman">Docker&nbsp;<span style="font-family: 宋体">主机会自动分配一个端口转发到指定的端口。</span></span></span></span></span></span></p>
<p class="p0"><strong>ENV</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">ENV&nbsp;&lt;key&gt;&nbsp;&lt;value&gt;<span style="font-family: 宋体">。&nbsp;指定一个环境变量,会被后续&nbsp;<span style="font-family: Times New Roman">RUN&nbsp;<span style="font-family: 宋体">指令使用,并在容器运行时保持。</span></span></span></span></p>
<p class="p0">例如</p>
<p class="p0">ENV&nbsp;PG_MAJOR&nbsp;9.3</p>
<p class="p0">ENV&nbsp;PG_VERSION&nbsp;9.3.4</p>
<p class="p0">RUN&nbsp;curl&nbsp;-SL&nbsp;http://example.com/postgres-$PG_VERSION.tar.xz&nbsp;|&nbsp;tar&nbsp;-xJC&nbsp;/usr/src/postgress&nbsp;&amp;&amp;&nbsp;…</p>
<p class="p0">ENV&nbsp;PATH&nbsp;/usr/local/postgres-$PG_MAJOR/bin:$PATH</p>
<p class="p0"><strong>ADD</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">ADD&nbsp;&lt;src&gt;&nbsp;&lt;dest&gt;<span style="font-family: 宋体">。</span></span></p>
<p class="p0">该命令将复制指定的&nbsp;<span style="font-family: Times New Roman">&lt;src&gt;&nbsp;<span style="font-family: 宋体">到容器中的&nbsp;<span style="font-family: Times New Roman">&lt;dest&gt;<span style="font-family: 宋体">。&nbsp;其中&nbsp;<span style="font-family: Times New Roman">&lt;src&gt;&nbsp;<span style="font-family: 宋体">可以是<span style="font-family: Times New Roman">Dockerfile<span style="font-family: 宋体">所在目录的一个相对路径;也可以是一个&nbsp;<span style="font-family: Times New Roman">URL<span style="font-family: 宋体">;还可以是一个&nbsp;<span style="font-family: Times New Roman">tar&nbsp;<span style="font-family: 宋体">文件(自动解压为目录)。</span></span></span></span></span></span></span></span></span></span></span></span></p>
<p class="p0"><strong>COPY</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">COPY&nbsp;&lt;src&gt;&nbsp;&lt;dest&gt;<span style="font-family: 宋体">。</span></span></p>
<p class="p0">复制本地主机的&nbsp;<span style="font-family: Times New Roman">&lt;src&gt;<span style="font-family: 宋体">(为&nbsp;<span style="font-family: Times New Roman">Dockerfile&nbsp;<span style="font-family: 宋体">所在目录的相对路径)到容器中的&nbsp;<span style="font-family: Times New Roman">&lt;dest&gt;<span style="font-family: 宋体">。</span></span></span></span></span></span></p>
<p class="p0">当使用本地目录为源目录时,推荐使用&nbsp;<span style="font-family: Times New Roman">COPY<span style="font-family: 宋体">。</span></span></p>
<p class="p0"><strong>ENTRYPOINT</strong></p>
<p class="p0">两种格式:</p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;ENTRYPOINT&nbsp;["executable",&nbsp;"param1",&nbsp;"param2"]</p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;ENTRYPOINT&nbsp;command&nbsp;param1&nbsp;param2<span style="font-family: 宋体">(<span style="font-family: Times New Roman">shell<span style="font-family: 宋体">中执行)。</span></span></span></p>
<p class="p0">配置容器启动后执行的命令,并且不可被&nbsp;<span style="font-family: Times New Roman">docker&nbsp;run&nbsp;<span style="font-family: 宋体">提供的参数覆盖。</span></span></p>
<p class="p0">每个&nbsp;<span style="font-family: Times New Roman">Dockerfile&nbsp;<span style="font-family: 宋体">中只能有一个&nbsp;<span style="font-family: Times New Roman">ENTRYPOINT<span style="font-family: 宋体">,当指定多个时,只有最后一个起效。</span></span></span></span></p>
<p class="p0"><strong>VOLUME</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">VOLUME&nbsp;["/data"]<span style="font-family: 宋体">。</span></span></p>
<p class="p0">创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。</p>
<p class="p0"><strong>USER</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">USER&nbsp;daemon<span style="font-family: 宋体">。</span></span></p>
<p class="p0">指定运行容器时的用户名或&nbsp;<span style="font-family: Times New Roman">UID<span style="font-family: 宋体">,后续的&nbsp;<span style="font-family: Times New Roman">RUN&nbsp;<span style="font-family: 宋体">也会使用指定用户。</span></span></span></span></p>
<p class="p0">当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户,例如:<span style="font-family: Times New Roman">RUN&nbsp;groupadd&nbsp;-r&nbsp;postgres&nbsp;&amp;&amp;&nbsp;useradd&nbsp;-r&nbsp;-g&nbsp;postgres&nbsp;postgres<span style="font-family: 宋体">。要临时获取管理员权限可以使用&nbsp;<span style="font-family: Times New Roman">gosu<span style="font-family: 宋体">,而不推荐&nbsp;<span style="font-family: Times New Roman">sudo<span style="font-family: 宋体">。</span></span></span></span></span></span></p>
<p class="p0"><strong>WORKDIR</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">WORKDIR&nbsp;/path/to/workdir<span style="font-family: 宋体">。</span></span></p>
<p class="p0">为后续的&nbsp;<span style="font-family: Times New Roman">RUN<span style="font-family: 宋体">、<span style="font-family: Times New Roman">CMD<span style="font-family: 宋体">、<span style="font-family: Times New Roman">ENTRYPOINT&nbsp;<span style="font-family: 宋体">指令配置工作目录。</span></span></span></span></span></span></p>
<p class="p0">可以使用多个&nbsp;<span style="font-family: Times New Roman">WORKDIR&nbsp;<span style="font-family: 宋体">指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如</span></span></p>
<p class="p0">WORKDIR&nbsp;/a</p>
<p class="p0">WORKDIR&nbsp;b</p>
<p class="p0">WORKDIR&nbsp;c</p>
<p class="p0">RUN&nbsp;pwd</p>
<p class="p0">则最终路径为&nbsp;<span style="font-family: Times New Roman">/a/b/c<span style="font-family: 宋体">。</span></span></p>
<p class="p0"><strong>ONBUILD</strong></p>
<p class="p0">格式为&nbsp;<span style="font-family: Times New Roman">ONBUILD&nbsp;<span style="font-family: 宋体">。</span></span></p>
<p class="p0">配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。</p>
<p class="p0">例如,<span style="font-family: Times New Roman">Dockerfile&nbsp;<span style="font-family: 宋体">使用如下的内容创建了镜像&nbsp;<span style="font-family: Times New Roman">image-A<span style="font-family: 宋体">。</span></span></span></span></p>
<p class="p0">[...]</p>
<p class="p0">ONBUILD&nbsp;ADD&nbsp;.&nbsp;/app/src</p>
<p class="p0">ONBUILD&nbsp;RUN&nbsp;/usr/local/bin/python-build&nbsp;--dir&nbsp;/app/src</p>
<p class="p0">[...]</p>
<p class="p0">如果基于&nbsp;<span style="font-family: Times New Roman">image-A&nbsp;<span style="font-family: 宋体">创建新的镜像时,新的<span style="font-family: Times New Roman">Dockerfile<span style="font-family: 宋体">中使用&nbsp;<span style="font-family: Times New Roman">FROM&nbsp;image-A<span style="font-family: 宋体">指定基础镜像时,会自动执行&nbsp;<span style="font-family: Times New Roman">ONBUILD&nbsp;<span style="font-family: 宋体">指令内容,等价于在后面添加了两条指令。</span></span></span></span></span></span></span></span></p>
<p class="p0">FROM&nbsp;image-A&nbsp;#Automatically&nbsp;run&nbsp;the&nbsp;followingADD&nbsp;.&nbsp;/app/srcRUN&nbsp;/usr/local/bin/python-build&nbsp;--dir&nbsp;/app/src</p>
<p class="p0">使用&nbsp;<span style="font-family: Times New Roman">ONBUILD&nbsp;<span style="font-family: 宋体">指令的镜像,推荐在标签中注明,例如&nbsp;<span style="font-family: Times New Roman">ruby:1.9-onbuild<span style="font-family: 宋体">。</span></span></span></span></p>
</blockquote>
<h1>3.创建镜像</h1>
<p class="p0">编写完Dockerfile文件后,通过运行<span style="font-family: Times New Roman">docker&nbsp;build</span><span style="font-family: 宋体">命令</span>来创建自定义的镜像。<span style="font-family: Times New Roman">Docker&nbsp;build</span><span style="font-family: 宋体">命令格式如下:</span></p>
<blockquote>
<p class="p0"><span style="font-family: 宋体">docker&nbsp;build&nbsp;&nbsp;&lt;path&gt;</span></p>
<p class="p0"><span style="font-family: 宋体">该命令将读取指定路径下(包括子目录)的&nbsp;<span style="font-family: Times New Roman">Dockerfile<span style="font-family: 宋体">,并将该路径下所有内容发送给&nbsp;<span style="font-family: Times New Roman">Docker&nbsp;<span style="font-family: 宋体">服务端,由服务端来创建镜像。因此一般建议放置&nbsp;<span style="font-family: Times New Roman">Dockerfile&nbsp;<span style="font-family: 宋体">的目录为空目录。也可以通过&nbsp;<span style="font-family: Times New Roman">.dockerignore&nbsp;<span style="font-family: 宋体">文件(每一行添加一条匹配模式)来让&nbsp;<span style="font-family: Times New Roman">Docker&nbsp;<span style="font-family: 宋体">忽略路径下的目录和文件。</span></span></span></span></span></span></span></span></span></span></span></p>
</blockquote>
<p class="p0">例如下面使用<span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">样例来创建了镜像</span><span style="font-family: Times New Roman">test:0.0.1</span><span style="font-family: 宋体">,其中</span><span style="font-family: Times New Roman">-t</span><span style="font-family: 宋体">选项用来指定镜像的</span><span style="font-family: Times New Roman">tag</span><span style="font-family: 宋体">。Dockerfile文件内容如下:</span></p>
<div class="cnblogs_code">
<pre>FROM ubuntu:14.04
MAINTAINER lienhua34@xxx.com

RUN mkdir /opt/leh
RUN touch /opt/leh/test

CMD echo "Hello lienhua34"</pre>
</div>
<p>下面运行docker build命令生成镜像test:0.0.1,</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">lienhua34@test$</span> <span style="color: rgba(0, 0, 255, 1)">sudo</span> docker build -t test:<span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)"> .
Sending build context to Docker daemon </span><span style="color: rgba(128, 0, 128, 1)">3.072</span><span style="color: rgba(0, 0, 0, 1)"> kB
Step </span><span style="color: rgba(128, 0, 128, 1)">1</span> : FROM ubuntu:<span style="color: rgba(128, 0, 128, 1)">14.04</span>
---&gt;<span style="color: rgba(0, 0, 0, 1)"> a5a467fddcb8
Step </span><span style="color: rgba(128, 0, 128, 1)">2</span> : MAINTAINER lienhua34@<span style="color: rgba(128, 0, 128, 1)">163</span><span style="color: rgba(0, 0, 0, 1)">.com
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> ce9e7b02f075
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 332259a92e74
Removing intermediate container ce9e7b02f075
Step </span><span style="color: rgba(128, 0, 128, 1)">3</span> : RUN <span style="color: rgba(0, 0, 255, 1)">mkdir</span> /opt/<span style="color: rgba(0, 0, 0, 1)">leh
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> e93f0a98040f
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 097e177cf37f
Removing intermediate container e93f0a98040f
Step </span><span style="color: rgba(128, 0, 128, 1)">4</span> : RUN <span style="color: rgba(0, 0, 255, 1)">touch</span> /opt/leh/<span style="color: rgba(0, 0, 0, 1)">test
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> f1531d3dea1a
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 0f68852f8356
Removing intermediate container f1531d3dea1a
Step </span><span style="color: rgba(128, 0, 128, 1)">5</span> : CMD <span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello lienhua34</span><span style="color: rgba(128, 0, 0, 1)">"</span>
---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> cf3c5ce2af46
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 811ce27ce692
Removing intermediate container cf3c5ce2af46
Successfully built 811ce27ce692</span></pre>
</div>
<p>然后启动该镜像的容器来查看结果,</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">lienhua34@test$</span> <span style="color: rgba(0, 0, 255, 1)">sudo</span><span style="color: rgba(0, 0, 0, 1)"> docker images
REPOSITORY                   TAG               IMAGE ID            CREATED             VIRTUAL SIZE
test                         </span><span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">1</span>               811ce27ce692      <span style="color: rgba(128, 0, 128, 1)">32</span> seconds ago      <span style="color: rgba(128, 0, 128, 1)">187.9</span><span style="color: rgba(0, 0, 0, 1)"> MB
<span style="color: rgba(0, 128, 0, 1)">lienhua34@test$ </span></span><span style="color: rgba(0, 0, 255, 1)">sudo</span> docker run -ti test:<span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">
Hello lienhua34</span></pre>
</div>
<p class="p0">Dockerfile<span style="font-family: 宋体">文件的每条指令生成镜像的一层(</span><span style="color: rgba(255, 0, 0, 1)">注:一个镜像不能超过</span><span style="font-family: Times New Roman; color: rgba(255, 0, 0, 1)">127</span><span style="font-family: 宋体; color: rgba(255, 0, 0, 1)">层</span>)。<span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">中的指令被一条条地执行。每一步都创建一个新的容器,在容器中执行指令并提交修改。当所有指令执行完毕后,返回最终的镜像</span><span style="font-family: Times New Roman">id</span><span style="font-family: 宋体">。</span></p>
<h1>4.Dockerfile文件中的CMD和ENTRYPOINT指令差异对比</h1>
<p class="p0">CMD<span style="font-family: 宋体">指令和</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指令的作用都是为镜像指定容器启动后的命令,那么它们两者之间有什么各自的优点呢?</span></p>
<p class="p0">为了更好地对比<span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指令和</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指令的差异,我们这里再列一下这两个指令的说明,</span></p>
<blockquote>
<p class="p0"><strong>CMD</strong></p>
<p class="p0">支持三种格式</p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;CMD&nbsp;["executable","param1","param2"]&nbsp;<span style="font-family: 宋体">使用&nbsp;<span style="font-family: Times New Roman">exec&nbsp;<span style="font-family: 宋体">执行,推荐方式;</span></span></span></p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;CMD&nbsp;command&nbsp;param1&nbsp;param2&nbsp;<span style="font-family: 宋体">在&nbsp;<span style="font-family: Times New Roman">/bin/sh&nbsp;<span style="font-family: 宋体">中执行,提供给需要交互的应用;</span></span></span></p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;CMD&nbsp;["param1","param2"]&nbsp;<span style="font-family: 宋体">提供给&nbsp;<span style="font-family: Times New Roman">ENTRYPOINT&nbsp;<span style="font-family: 宋体">的默认参数;</span></span></span></p>
<p class="p0">指定启动容器时执行的命令,每个&nbsp;<span style="font-family: Times New Roman">Dockerfile&nbsp;<span style="font-family: 宋体">只能有一条&nbsp;<span style="font-family: Times New Roman">CMD&nbsp;<span style="font-family: 宋体">命令。如果指定了多条命令,只有最后一条会被执行。</span></span></span></span></p>
<p class="p0">如果用户启动容器时候指定了运行的命令,则会覆盖掉&nbsp;<span style="font-family: Times New Roman">CMD&nbsp;<span style="font-family: 宋体">指定的命令。</span></span></p>
<p class="p0"><strong>ENTRYPOINT</strong></p>
<p class="p0">两种格式:</p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;ENTRYPOINT&nbsp;["executable",&nbsp;"param1",&nbsp;"param2"]</p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;ENTRYPOINT&nbsp;command&nbsp;param1&nbsp;param2<span style="font-family: 宋体">(<span style="font-family: Times New Roman">shell<span style="font-family: 宋体">中执行)。</span></span></span></p>
<p class="p0">配置容器启动后执行的命令,并且不可被&nbsp;<span style="font-family: Times New Roman">docker&nbsp;run&nbsp;<span style="font-family: 宋体">提供的参数覆盖。</span></span></p>
<p class="p0">每个&nbsp;<span style="font-family: Times New Roman">Dockerfile&nbsp;<span style="font-family: 宋体">中只能有一个&nbsp;<span style="font-family: Times New Roman">ENTRYPOINT<span style="font-family: 宋体">,当指定多个时,只有最后一个起效。</span></span></span></span></p>
</blockquote>
<p class="p0">从上面的说明,我们可以看到有两个共同点:</p>
<ol>
<li class="p0"><strong><span style="font-family: 宋体">都可以指定</span><span style="font-family: Times New Roman">shell</span><span style="font-family: 宋体">或</span><span style="font-family: Times New Roman">exec</span><span style="font-family: 宋体">函数调用的方式执行命令;</span></strong></li>
<li class="p0"><strong><span style="font-family: 宋体">当存在多个</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指令或</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指令时,只有最后一个生效;</span></strong></li>
</ol>
<p class="p0">而它们有如下差异:</p>
<p class="p0">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>差异<span style="font-family: Times New Roman">1</span><span style="font-family: 宋体">:</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指令指定的容器启动时命令可以被</span><span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">指定的命令覆盖,而</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指令指定的命令不能被覆盖,而是将</span><span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">指定的参数当做</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指定命令的参数。</span></strong></p>
<p class="p0"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 差异<span style="font-family: Times New Roman">2</span><span style="font-family: 宋体">:</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指令可以为</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指令设置默认参数,</span>而且可以被<span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">指定的参数覆盖;</span></strong></p>
<p class="p0">下面分别对上面两个差异点进行详细说明,</p>
<h2>4.1&nbsp;差异1</h2>
<blockquote>
<p>CMD<span style="font-family: 宋体">指令指定的容器启动时命令可以被<span style="font-family: Times New Roman">docker&nbsp;run<span style="font-family: 宋体">指定的命令覆盖;而<span style="font-family: Times New Roman">ENTRYPOINT<span style="font-family: 宋体">指令指定的命令不能被覆盖,而是将<span style="font-family: Times New Roman">docker&nbsp;run<span style="font-family: 宋体">指定的参数当做<span style="font-family: Times New Roman">ENTRYPOINT<span style="font-family: 宋体">指定命令的参数。</span></span></span></span></span></span></span></span></span></p>
</blockquote>
<p class="p0">下面有个命名为<span style="font-family: Times New Roman">startup</span><span style="font-family: 宋体">的可执行</span><span style="font-family: Times New Roman">shell</span><span style="font-family: 宋体">脚本,其功能就是输出命令行参数而已。内容如下所示,</span></p>
<div class="cnblogs_code">
<pre>#!/bin/<span style="color: rgba(0, 0, 0, 1)">bash

</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "in startup, args: $@"</pre>
</div>
<h3 class="p0">通过<span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指定容器启动时命令:</span></h3>
<p class="p0">现在我们新建一个<span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">文件,其将</span><span style="font-family: Times New Roman">startup</span><span style="font-family: 宋体">脚本拷贝到容器的</span><span style="font-family: Times New Roman">/opt</span><span style="font-family: 宋体">目录下,并通过</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指令指定容器启动时运行该</span><span style="font-family: Times New Roman">startup</span><span style="font-family: 宋体">脚本。其内容如下,</span></p>
<div class="cnblogs_code">
<pre>FROM ubuntu:14.04
MAINTAINER lienhua34@xxx.com

ADD startup /opt
RUN chmod a+x /opt/startup

CMD ["/opt/startup"]</pre>
</div>
<p class="p0">然后我们通过运行<span style="font-family: Times New Roman">docker&nbsp;build</span><span style="font-family: 宋体">命令生成</span><span style="font-family: Times New Roman">test:latest</span><span style="font-family: 宋体">镜像,</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">lienhua34@test$</span> <span style="color: rgba(0, 0, 255, 1)">sudo</span> docker build -<span style="color: rgba(0, 0, 0, 1)">t test .
Sending build context to Docker daemon </span><span style="color: rgba(128, 0, 128, 1)">4.096</span><span style="color: rgba(0, 0, 0, 1)"> kB
Step </span><span style="color: rgba(128, 0, 128, 1)">1</span> : FROM ubuntu:<span style="color: rgba(128, 0, 128, 1)">14.04</span>
---&gt;<span style="color: rgba(0, 0, 0, 1)"> a5a467fddcb8
Step </span><span style="color: rgba(128, 0, 128, 1)">2</span> : MAINTAINER lienhua34@<span style="color: rgba(128, 0, 128, 1)">163</span><span style="color: rgba(0, 0, 0, 1)">.com
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> Using cache
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 332259a92e74
Step </span><span style="color: rgba(128, 0, 128, 1)">3</span> : ADD startup /<span style="color: rgba(0, 0, 0, 1)">opt
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 3c26b6a8ef1b
Removing intermediate container 87022b0f30c5
Step </span><span style="color: rgba(128, 0, 128, 1)">4</span> : RUN <span style="color: rgba(0, 0, 255, 1)">chmod</span> a+x /opt/<span style="color: rgba(0, 0, 0, 1)">startup
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> 4518ba223345
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 04d9b53d6148
Removing intermediate container 4518ba223345
Step </span><span style="color: rgba(128, 0, 128, 1)">5</span> : CMD /opt/<span style="color: rgba(0, 0, 0, 1)">startup
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> 64a07c2f5e64
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 18a2d5066346
Removing intermediate container 64a07c2f5e64
Successfully built 18a2d5066346</span></pre>
</div>
<p class="p0">然后使用<span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">启动两个</span><span style="font-family: Times New Roman">test:latest</span><span style="font-family: 宋体">镜像的容器,第一个</span><span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">命令没有指定容器启动时命令,第二个</span><span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">命令指定了容器启动时的命令为</span><span style="font-family: Times New Roman">“</span>/bin/bash&nbsp;-c&nbsp;'echo&nbsp;Hello'”<span style="font-family: 宋体">,</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">lienhua34@test$</span> <span style="color: rgba(0, 0, 255, 1)">sudo</span> docker run -ti --<span style="color: rgba(0, 0, 255, 1)">rm</span>=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> test
</span><span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> startup, args:
<span style="color: rgba(0, 128, 0, 1)">lienhua34@test$</span> </span><span style="color: rgba(0, 0, 255, 1)">sudo</span> docker run -ti --<span style="color: rgba(0, 0, 255, 1)">rm</span>=<span style="color: rgba(0, 0, 255, 1)">true</span> test /bin/bash -c <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">echo Hello</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
Hello</span></pre>
</div>
<p class="p0">从上面运行结果可以看到,docker&nbsp;run<span style="font-family: 宋体">命令启动容器时指定的运行命令覆盖了</span><span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">文件中</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指令指定的命令</span>。</p>
<h3 class="p0">通过<span style="font-family: Times New Roman">ENTRYPOINT</span>指定容器启动时命令:</h3>
<p class="p0">将上面的<span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">中的</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">替换成</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">,内容如下所示,</span></p>
<div class="cnblogs_code">
<pre>FROM ubuntu:14.04
MAINTAINER lienhua34@xxx.com

ADD startup /opt
RUN chmod a+x /opt/startup

ENTRYPOINT [“/opt/startup”]</pre>
</div>
<p class="p0">同样,通过运行<span style="font-family: Times New Roman">docker&nbsp;build</span><span style="font-family: 宋体">生成</span><span style="font-family: Times New Roman">test:latest</span><span style="font-family: 宋体">镜像,</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">lienhua34@test$</span> <span style="color: rgba(0, 0, 255, 1)">sudo</span> docker build -<span style="color: rgba(0, 0, 0, 1)">t test .
Sending build context to Docker daemon </span><span style="color: rgba(128, 0, 128, 1)">4.096</span><span style="color: rgba(0, 0, 0, 1)"> kB
Step </span><span style="color: rgba(128, 0, 128, 1)">1</span> : FROM ubuntu:<span style="color: rgba(128, 0, 128, 1)">14.04</span>
---&gt;<span style="color: rgba(0, 0, 0, 1)"> a5a467fddcb8
Step </span><span style="color: rgba(128, 0, 128, 1)">2</span> : MAINTAINER lienhua34@<span style="color: rgba(128, 0, 128, 1)">163</span><span style="color: rgba(0, 0, 0, 1)">.com
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> Using cache
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 332259a92e74
Step </span><span style="color: rgba(128, 0, 128, 1)">3</span> : ADD startup /<span style="color: rgba(0, 0, 0, 1)">opt
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> Using cache
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 3c26b6a8ef1b
Step </span><span style="color: rgba(128, 0, 128, 1)">4</span> : RUN <span style="color: rgba(0, 0, 255, 1)">chmod</span> a+x /opt/<span style="color: rgba(0, 0, 0, 1)">startup
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> Using cache
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 04d9b53d6148
Step </span><span style="color: rgba(128, 0, 128, 1)">5</span> : ENTRYPOINT /opt/<span style="color: rgba(0, 0, 0, 1)">startup
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> cdec60940ad7
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 78f8aca2edc2
Removing intermediate container cdec60940ad7
Successfully built 78f8aca2edc2</span></pre>
</div>
<p class="p0">然后使用<span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">启动两个</span><span style="font-family: Times New Roman">test:latest</span><span style="font-family: 宋体">镜像的容器,第一个</span><span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">命令没有指定容器启动时命令,第二个</span><span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">命令指定了容器启动时的命令为</span><span style="font-family: Times New Roman">“</span>/bin/bash&nbsp;-c&nbsp;'echo&nbsp;Hello'”<span style="font-family: 宋体">,</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">lienhua34@test$</span> <span style="color: rgba(0, 0, 255, 1)">sudo</span> docker run -ti --<span style="color: rgba(0, 0, 255, 1)">rm</span>=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> test
</span><span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> startup, args:
lienhua34@test$ </span><span style="color: rgba(0, 0, 255, 1)">sudo</span> docker run -ti --<span style="color: rgba(0, 0, 255, 1)">rm</span>=<span style="color: rgba(0, 0, 255, 1)">true</span> test /bin/bash -c <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">echo Hello</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 0, 255, 1)">in</span> startup, args: /bin/bash -c <span style="color: rgba(0, 0, 255, 1)">echo</span> Hello</pre>
</div>
<p class="p0">通过上面的运行结果可以看出,<span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">命令指定的容器运行命令不能覆盖</span><span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">文件中</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指令指定的命令,反而被当做参数传递给</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指令指定的命令。</span></p>
<h2>4.2&nbsp;差异2</h2>
<blockquote>
<p>CMD<span style="font-family: 宋体">指令可以为<span style="font-family: Times New Roman">ENTRYPOINT<span style="font-family: 宋体">指令设置默认参数,而且可以被<span style="font-family: Times New Roman">docker&nbsp;run<span style="font-family: 宋体">指定的参数覆盖;</span></span></span></span></span></p>
</blockquote>
<p class="p0">同样使用上面的<span style="font-family: Times New Roman">startup</span><span style="font-family: 宋体">脚本。编写</span><span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">,内容如下所示,</span></p>
<div class="cnblogs_code">
<pre>FROM ubuntu:<span style="color: rgba(128, 0, 128, 1)">14.04</span><span style="color: rgba(0, 0, 0, 1)">
MAINTAINER lienhua34@xxx.com

ADD startup </span>/<span style="color: rgba(0, 0, 0, 1)">opt
RUN </span><span style="color: rgba(0, 0, 255, 1)">chmod</span> a+x /opt/<span style="color: rgba(0, 0, 0, 1)">startup

ENTRYPOINT [</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/opt/startup</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">arg1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">]
CMD [</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">arg2</span><span style="color: rgba(128, 0, 0, 1)">"</span>]</pre>
</div>
<p class="p0">运行<span style="font-family: Times New Roman">docker&nbsp;build</span><span style="font-family: 宋体">命令生成</span><span style="font-family: Times New Roman">test:latest</span><span style="font-family: 宋体">镜像,</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">lienhua34@test$</span> <span style="color: rgba(0, 0, 255, 1)">sudo</span> docker build -<span style="color: rgba(0, 0, 0, 1)">t test .
Sending build context to Docker daemon </span><span style="color: rgba(128, 0, 128, 1)">4.096</span><span style="color: rgba(0, 0, 0, 1)"> kB
Step </span><span style="color: rgba(128, 0, 128, 1)">1</span> : FROM ubuntu:<span style="color: rgba(128, 0, 128, 1)">14.04</span>
---&gt;<span style="color: rgba(0, 0, 0, 1)"> a5a467fddcb8
Step </span><span style="color: rgba(128, 0, 128, 1)">2</span> : MAINTAINER lienhua34@<span style="color: rgba(128, 0, 128, 1)">163</span><span style="color: rgba(0, 0, 0, 1)">.com
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> Using cache
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 332259a92e74
Step </span><span style="color: rgba(128, 0, 128, 1)">3</span> : ADD startup /<span style="color: rgba(0, 0, 0, 1)">opt
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> Using cache
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 3c26b6a8ef1b
Step </span><span style="color: rgba(128, 0, 128, 1)">4</span> : RUN <span style="color: rgba(0, 0, 255, 1)">chmod</span> a+x /opt/<span style="color: rgba(0, 0, 0, 1)">startup
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> Using cache
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 04d9b53d6148
Step </span><span style="color: rgba(128, 0, 128, 1)">5</span> : ENTRYPOINT /opt/<span style="color: rgba(0, 0, 0, 1)">startup arg1
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> 54947233dc3d
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 15a485253b4e
Removing intermediate container 54947233dc3d
Step </span><span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)"> : CMD arg2
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> 18c43d2d90fd
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 4684ba457cc2
Removing intermediate container 18c43d2d90fd
Successfully built 4684ba457cc2</span></pre>
</div>
<p class="p0">下面运行<span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">启动两个</span><span style="font-family: Times New Roman">test:latest</span><span style="font-family: 宋体">镜像的容器,第一条</span><span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">命令没有指定参数,第二条</span><span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">命令指定了参数</span><span style="font-family: Times New Roman">arg3</span><span style="font-family: 宋体">,其运行结果如下,</span></p>
<div class="cnblogs_code">
<pre>lienhua34@test$ <span style="color: rgba(0, 0, 255, 1)">sudo</span> docker run -ti --<span style="color: rgba(0, 0, 255, 1)">rm</span>=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> test
</span><span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> startup, args: arg1 arg2
lienhua34@test$ </span><span style="color: rgba(0, 0, 255, 1)">sudo</span> docker run -ti --<span style="color: rgba(0, 0, 255, 1)">rm</span>=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> test arg3
</span><span style="color: rgba(0, 0, 255, 1)">in</span> startup, args: arg1 arg3</pre>
</div>
<p class="p0">从上面第一个容器的运行结果可以看出<span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指令为</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指令设置了默认参数;从第二个容器的运行结果看出,</span><span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">命令指定的参数覆盖了</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指令指定的参数。</span></p>
<h2>4.3注意点</h2>
<p class="p0"><span style="color: rgba(255, 0, 0, 1)"><strong>CMD<span style="font-family: 宋体">指令为</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指令提供默认参数是基于镜像层次结构生效的,而不是基于是否在同个</span><span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">文件中。意思就是说,如果</span><span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">指定基础镜像中是</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指定的启动命令,则该</span><span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">中的</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">依然是为基础镜像中的</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">设置默认参数。</span></strong></span></p>
<p class="p0">例如,我们有如下一个<span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">文件,</span></p>
<div class="cnblogs_code">
<pre>FROM ubuntu:14.04
MAINTAINER lienhua34@xxx.com

ADD startup /opt
RUN chmod a+x /opt/startup

ENTRYPOINT ["/opt/startup", "arg1"]</pre>
</div>
<p class="p0">通过运行<span style="font-family: Times New Roman">docker&nbsp;build</span><span style="font-family: 宋体">命令生成</span><span style="font-family: Times New Roman">test:0.0.1</span><span style="font-family: 宋体">镜像,然后创建该镜像的一个容器,查看运行结果,</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">lienhua34@test$</span> <span style="color: rgba(0, 0, 255, 1)">sudo</span> docker build -t test:<span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)"> .
Sending build context to Docker daemon </span><span style="color: rgba(128, 0, 128, 1)">6.144</span><span style="color: rgba(0, 0, 0, 1)"> kB
Step </span><span style="color: rgba(128, 0, 128, 1)">1</span> : FROM ubuntu:<span style="color: rgba(128, 0, 128, 1)">14.04</span>
---&gt;<span style="color: rgba(0, 0, 0, 1)"> a5a467fddcb8
Step </span><span style="color: rgba(128, 0, 128, 1)">2</span> : MAINTAINER lienhua34@<span style="color: rgba(128, 0, 128, 1)">163</span><span style="color: rgba(0, 0, 0, 1)">.com
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> 57a96522061a
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> c3bbf1bd8068
Removing intermediate container 57a96522061a
Step </span><span style="color: rgba(128, 0, 128, 1)">3</span> : ADD startup /<span style="color: rgba(0, 0, 0, 1)">opt
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> f9884fbc7607
Removing intermediate container 591a82b2f382
Step </span><span style="color: rgba(128, 0, 128, 1)">4</span> : RUN <span style="color: rgba(0, 0, 255, 1)">chmod</span> a+x /opt/<span style="color: rgba(0, 0, 0, 1)">startup
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> 7a19f10b5513
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 16c03869a764
Removing intermediate container 7a19f10b5513
Step </span><span style="color: rgba(128, 0, 128, 1)">5</span> : ENTRYPOINT /opt/<span style="color: rgba(0, 0, 0, 1)">startup arg1
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> b581c32b25c3
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> c6b1365afe03
Removing intermediate container b581c32b25c3
Successfully built c6b1365afe03
<span style="color: rgba(0, 128, 0, 1)">lienhua34@test$ </span></span><span style="color: rgba(0, 0, 255, 1)">sudo</span> docker run -ti --<span style="color: rgba(0, 0, 255, 1)">rm</span>=<span style="color: rgba(0, 0, 255, 1)">true</span> test:<span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">1</span>
<span style="color: rgba(0, 0, 255, 1)">in</span> startup, args: arg1</pre>
</div>
<p class="p0">下面新建一个<span style="font-family: Times New Roman">Dockerfile</span><span style="font-family: 宋体">文件,基础镜像是刚生成的</span><span style="font-family: Times New Roman">test:0.0.1</span><span style="font-family: 宋体">,通过</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指定要通过</span><span style="font-family: Times New Roman">echo</span><span style="font-family: 宋体">打印字符串</span><span style="font-family: Times New Roman">“in&nbsp;test:0.0.2”</span><span style="font-family: 宋体">。文件内容如下所示,</span></p>
<div class="cnblogs_code">
<pre>FROM test:0.0.1
MAINTAINER lienhua34@xxx.com

CMD ["/bin/bash", "-c", "echo in test:0.0.2"]</pre>
</div>
<p class="p0">运行<span style="font-family: Times New Roman">docker&nbsp;build</span><span style="font-family: 宋体">命令生成</span><span style="font-family: Times New Roman">test:0.0.2</span><span style="font-family: 宋体">镜像,然后通过运行</span><span style="font-family: Times New Roman">docker&nbsp;run</span><span style="font-family: 宋体">启动一个</span><span style="font-family: Times New Roman">test:0.0.2</span><span style="font-family: 宋体">镜像的容器来查看结果,</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">lienhua34@test$</span> <span style="color: rgba(0, 0, 255, 1)">sudo</span> docker build -t test:<span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)"> .
Sending build context to Docker daemon </span><span style="color: rgba(128, 0, 128, 1)">6.144</span><span style="color: rgba(0, 0, 0, 1)"> kB
Step </span><span style="color: rgba(128, 0, 128, 1)">1</span> : FROM test:<span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">1</span>
---&gt;<span style="color: rgba(0, 0, 0, 1)"> c6b1365afe03
Step </span><span style="color: rgba(128, 0, 128, 1)">2</span> : MAINTAINER lienhua34@<span style="color: rgba(128, 0, 128, 1)">163</span><span style="color: rgba(0, 0, 0, 1)">.com
</span>---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> deca95cf4c15
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 971b5a819b48
Removing intermediate container deca95cf4c15
Step </span><span style="color: rgba(128, 0, 128, 1)">3</span> : CMD /bin/bash -c <span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(0, 0, 255, 1)">in</span> test:<span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">2</span>
---&gt; Running <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> 4a31c4652e1e
</span>---&gt;<span style="color: rgba(0, 0, 0, 1)"> 0ca06ba31405
Removing intermediate container 4a31c4652e1e
Successfully built 0ca06ba31405
<span style="color: rgba(0, 128, 0, 1)">lienhua34@test$ </span></span><span style="color: rgba(0, 0, 255, 1)">sudo</span> docker run -ti --<span style="color: rgba(0, 0, 255, 1)">rm</span>=<span style="color: rgba(0, 0, 255, 1)">true</span> test:<span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">2</span>
<span style="color: rgba(0, 0, 255, 1)">in</span> startup, args: arg1 /bin/bash -c <span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(0, 0, 255, 1)">in</span> test:<span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">2</span></pre>
</div>
<p class="p0">从上面结果可以看到,镜像<span style="font-family: Times New Roman">test:0.0.2</span><span style="font-family: 宋体">启动的容器运行时并不是打印字符串</span><span style="font-family: Times New Roman">”in&nbsp;test:0.0.2”</span><span style="font-family: 宋体">,而是将</span><span style="font-family: Times New Roman">CMD</span><span style="font-family: 宋体">指令指定的命令当做基础镜像</span><span style="font-family: Times New Roman">test:0.0.1</span><span style="font-family: 宋体">中</span><span style="font-family: Times New Roman">ENTRYPOINT</span><span style="font-family: 宋体">指定的运行脚本</span><span style="font-family: Times New Roman">startup</span><span style="font-family: 宋体">的参数。</span></p>
<p class="p0">(done)</p><br><br>
来源:https://www.cnblogs.com/lienhua34/p/5170335.html
頁: [1]
查看完整版本: Dockerfile创建自定义Docker镜像以及CMD与ENTRYPOINT指令的比较