Docker中CMD和ENTRYPOINT指令的具体区别

178 阅读2分钟

引言

  • 前面介绍DockerFile文件的时候简单介绍了一下文件末尾CMD指令的作用,但是在分析一个项目的Dockerfile文件的末尾的时候还是有些看不懂,所以本文详细扒一扒该参数的具体作用

  • 下图为Docker容器总结4关于该参数的一个简单介绍

  • 下图为我遇到的实际情况。

正文

容器与CMD的关系

  • 前面文章我将容器比喻成"压缩胶囊",但其实Docker本身并不是虚拟机,而是进程;
  • 那么在启动容器的时候,是需要指定所运行的程序及参数的。
    • CMD 指令就是用于指定默认的容器主进程的启动命令的。

CMD的相关介绍

  • CMD指令的格式有两种格式:
    • shell 格式:CMD <命令>
    • exec格式:CMD ["可执行文件", "参数1", "参数2"...]
  • 注: 通常Docker中推荐使用exec格式语法,这类格式在解析时会被解析为JSON数组,因此一定要使用双引号 ",而不要使用单引号。(原因可以看下json的组成格式)
    • 原因1:shell格式语法下一般会通过/bin/sh -c来执行命令;例如CMD echo $PATH,其实实际执行过程会变成CMD [ "sh", "-c", "echo $PATH" ],这样的话,环境变量会被 shell 进行解析处理掉
    • 原因2:有些镜像是不包含Shell的,那使用shell格式下的命令无法被正常执行。
    • 同理使用exec格式时需要获取环境变量的值,如果无法获取则可以考虑使用shell格式语法
  • 注:前面提到过对于CMD指定的命令,参数,不可以通过docker run命令行实现传递参数。因为命令行参数中指定的命令、参数与其是冲突的,如果命令行有就会把CMD部分覆盖掉

ENTRYPOINT的相关介绍

  • 其他的同理,格式同CMD一致,也是有两种方式,shell和exec
    • shell格式ENTRYPOINT 命令 参数1 参数2
    • exec格式ENTRYPOINT ["命令", "参数1", "参数2"]
    • 同样Docker推荐使用exec格式
  • 注:ENTRYPOINT指令其实所设置命令、参数也可被docker run命令行参数中指定要运行的命令 覆盖, 但需要使用--entrypoint选项进行显式覆盖。否则将会忽略命令行参数(是在命令行使用哈)

组合使用

  • 大多数场景下,CMD、ENTRYPOINT指令都是互相通用的,而且一般也会只使用其中一种指令,实际使用时对于组合使用二者来说,一般是通过exec格式的ENTRYPOINT设置固定的命令、参数,而利用exec格式的CMD设置默认的可变参数;
  • 换句话说:CMD指令方便镜像使用者更改容器运行的命令,故适用于较为灵活的场景;而如果不期望镜像使用者去轻易更改容器运行的命令,故推荐使用ENTRYPOINT指令;