三者都可用于执行命令,但无论在目的、运行时机、用法等方面都存在差异:

RUN instruction will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile.

An ENTRYPOINT allows you to configure a container that will run as an executable.

The main purpose of a CMD is to provide defaults

 

shell形式和exec形式

RUN指令有两种形式:

  • shell形式
    RUN command param1 param2
  • exec形式
    RUN ["executable", "param1", "param2"]             #方括号,引号

ENTRYPOINT也如此:

  • shell形式
    ENTRYPOINT command param1 param2
  • exec形式
    ENTRYPOINT ["executable", "param1", "param2"]

CMD还多了一种用于为ENTRYPOINT提供参数的形式:

  • shell形式
    CMD command param1 param2
  • exec形式
    CMD ["executable", "param1", "param2"]
  • 参数形式
    CMD ["param1","param2"]              #跟entrypoint联合使用,作为entrypiont的参数

shell形式和exec的形式的本质区别在于shell形式提供了默认的指令/bin/sh -c,所以其指定的command将在shell的环境下运行。因此指定command的pid将不会是1,因为pid为1的是shell,command进程是shell的子进程。

shell形式还有一个严重的问题:由于其默认使用/bin/sh来运行命令,如果镜像中不包含/bin/sh,容器会无法启动。

exec形式则不然,其直接运行指定的指令:

由于exec指定的命令不由shell启动,因此也就无法使用shell中的环境变量,如$HOME。如果希望能够使用环境变量,可以指定命令为sh:CMD [ "sh", "-c", "echo", "$HOME" ]

 

Dockerfile中只有最后一个CMD指令会生效,其他会被重载。

Dockerfile中只有最后一个ENTRYPOINT指令会生效,其他会被重载。

CMD指定的命令可以被docker run传递的命令覆盖。

CMD ["echo"]会被docker run --rm binss/test echo test中的echo覆盖,最终输出test。

ENTRYPOINT指定的命令不会被docker run传递的命令覆盖。容器名后面的所有内容都当成参数传递给其指定的命令。

ENTRYPOINT ["echo"]最终输出echo test。echo test都被当做是ENTRYPOINT指定的指令——echo的参数。

当然,ENTRYPOINT指定的命令并不是不能重载的,只需指定--entrypoint来重载即可。

 

=============

docker run -d -v /lib64:/lib64/ -v /data/log:/data/log ffmpeg_in_centos:v1  /data/ffmpeg -i rtmp://xxxx_input_url -f flv rtmp://output_url

在ffmpeg_in_centos:v1的镜像中运行  /data/ffmpeg程序,(也就是说ffmpeg必须被包含在ffmpeg_in_centos:v1镜像中)

如果一切顺利,你将在宿主机中看到一个运行着的ffmpeg前台进程,即使宿主机中没有ffmpeg这个进程,这就是docker的黑科技。

root     46739 46724 99 17:49 ?        00:31:48 /data/ffmpeg -i rtmp://xxxx_input_url -f flv rtmp://output_url

[root@ffmpeg]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a49711b14465 ffmpeg_in_centos:v1 "/data/ffmpeg -i" 21 minutes ago Up 21 minutes zen_carson

 

=============

docker exec :在运行的容器中执行命令

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

如果我们在当前的 Linux 操作系统下运行一个新的 Docker 容器,并通过 exec 进入其内部的 bash 并打印其中的全部进程,我们会得到以下的结果:

root@iZ255w13cy6Z:~# docker run -it -d ubuntu
b809a2eb3630e64c581561b08ac46154878ff1c61c6519848b4a29d412215e79
root@iZ255w13cy6Z:~# docker exec -it b809a2eb3630 /bin/bash
root@b809a2eb3630:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 15:42 pts/0    00:00:00 /bin/bash
root         9     0  0 15:42 pts/1    00:00:00 /bin/bash
root        17     9  0 15:43 pts/1    00:00:00 ps -ef