Docker CMD 与 ENTRYPOINT 的区别


CMD

The main purpose of a CMD is to provide defaults for an executing container. These defaults can include an executable, or they can omit the executable, in which case you must specify an ENTRYPOINT instruction as well.

CMD给出的是一个容器的默认的可执行体。也就是容器启动以后,默认的执行的命令。重点就是这个“默认”。意味着,如果docker run没有指定任何的执行命令或者dockerfile里面也没有entrypoint,那么就会使用CMD指定的默认的执行命令执行。同时也从侧面说明了entrypoint的含义,它才是真正的容器启动以后要执行命令。

这句话就给出了CMD命令的一个角色定位,它主要作用是默认的容器启动执行命令。(注意不是“全部”作用)

这也是为什么大多数网上博客论坛说的“CMD会被覆盖”,其实为什么会覆盖?因为CMD的角色定位就是默认,如果你不额外指定,那么就执行CMD的命令,否则呢?只要你指定了,那么就不会执行CMD,也就是CMD会被覆盖。

The CMD instruction has three forms:

  • CMD [“executable”,”param1”,”param2”] (exec form, this is the preferred form)

命令没有再任何shell终端环境下,如果我们要执行shell,必须把shell加入到中括号的参数中,比如

1
2
FROM centos
CMD ["/bin/bash", "-c", "echo 'hello cmd!'"]
  • CMD [“param1”,”param2”] (as default parameters to ENTRYPOINT)
  • CMD command param1 param2 (shell form)

command默认是在“/bin/sh -c”下执行的,比如

1
2
FROM centos
CMD echo "hello cmd!"

结果:命令行输出hello cmd!

Note:如果我们在run时指定了命令或者有entrypoint,那么CMD就会被覆盖,比如

1
docker run nginx echo hello

ENTRYPOINT

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

ENTRYPOINT才是正统地用于定义容器启动以后的执行体的,其实我们从名字也可以理解,这个是容器的“入口”。

ENTRYPOINT has two forms:

  • ENTRYPOINT [“executable”, “param1”, “param2”] (exec form, preferred)

  • ENTRYPOINT command param1 param2 (shell form)

在使用开源Docker时候需要注意: 第一种格式,与CMD有区别。如果run命令后面有东西,那么后面的全部都会作为entrypoint的参数,此时会覆盖CMD命令

如果run后面没有额外的东西,但是CMD有,那么CMD的全部内容会作为entrypoint的参数,这同时是CMD的第二种用法,这也是网上说的entrypoint不会被覆盖。

1
2
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["mysqld"]

当然如果要在run里面覆盖,也是有办法的,使用–entrypoint即可。


Refference