持续创作,加速成长!这是我参与「掘金日新计划 · 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. 最佳实践
- 使用RUN指令安装应用和软件包,构建镜像
- 如果Docker镜像的用途是运行程序或服务,比如运行一个MySQL,应该优先使用Exec个数的ENTRYPOINT指令。CMD可为ENTRYPOINT提供额外的默认参数
- 如果想为容器设置默认的启动命令,可以使用CMD指令。用户可在docker run 命令中替换此默认命令