Docker容器技术:Dockerfile中RUN与CMD与ENTRYPOINT

2,661 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

1. RUN

RUN: 执行命令并创建新的Image Layer

这个命令其实我们很熟悉的,之前笔记也有提过

2. CMD VS ENTRYPOINT

CMD:设置容器启动后默认执行的命令和参数

ENTRYPOINT:设置容器启动时运行的命令

这里需要实例来看,不然不容易区别,不过在此之前我们先介绍两种格式:

2.1 Shell和Exec格式

  • Shell格式就是把运行的命令当成是shell命令来填入,后面填的其实就是shell中我们会输入的命令!
  • Exec格式是需要特定格式来指明运行的命令和参数,通过,号分割。

这里我们来演示一下:

先定义第一个dockerfile:

然后docker build -t . 来执行Dockerfile制作image:

然后创建container:

这里结果符合预期。

接着我们把格式改成Exec格式:

接着同样执行上述命令,不过可以把tag换一下:

然后这里我们发现没有进行替换,直接打印字符了。

这是因为shell格式默认会通过shell去执行,可以识别$符号,进行替换。

但是Exec格式是单纯的去执行的echo命令而非在shell中执行,所以这里还需要指明我们这个命令是需要通过shell/bash进行的:

为啥是空的??

这里写法有问题,需要这样,把后面命令作为一个命令段:

然后重新build new image,run一下:

2.2 CMD

例如我们上面的Dockerfile,build run之后会自动输出 hello Docker

但是如果我们通过run -it 指定了别的命令(之前交互式启动就是这样的,默认打开bash),那么CMD就会被忽略掉

2.3 ENTRYPOINT

让容器以服务形式运行,通常作为一个后台进程。而不是像command一样默认去执行!

例如下面的mongoDB官方的image里面的Dockerfile就写了一个shell脚本,首先COPY脚本到指定位置,然后作为ENTRYPOINT。

3. 例子

这里看一个例子:

首先我们把退出的docker都删除:

然后我们可以为CMD和ENTRYPOINT对应两种格式分别建立一个image:

这里我们以cmd-shell和entrypoint-shell为例:

这里cmd会默认执行,直接输出:

如果我们指定了命令就会被覆盖,例如下面进入了容器的/bin/bash了:

接着我们看一下entrypoint的:

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

4. 最佳实践

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