背景说明

CMD和ENTRYPOINT都是用来指定容器启动时要运行的命令。

解决方案

特点对比

CMD

  1. 指定这个容器启动的时候要运行的命令,不可以追加命令,对命令可以覆盖
  2. CMD指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有其他传入值会覆盖根命令
  3. 该指令可以存在多个,存在多个时只有最后一个生效

    ENTRYPOINT

  4. 指定这个容器启动的时候要运行的命令,可以追加命令,对命令不能覆盖

  5. ENTRYPOINT 指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有其他传入值作为该命令的参数
  6. 该指令可以存在多个,存在多个时只有最后一个生效

    CMD

    默认命令

    假设针对如下Dockerfile
    1. FROM busybox
    2. WORKDIR /home/data
    3. RUN touch test.txt
    4. CMD ls /home/data
    执行镜像构建并运行,执行默认命令
    [root@vm1 cmd]# docker build . -t cmd:v1
    [root@vm1 cmd]# docker run cmd:v1
    test.txt
    [root@vm1 cmd]#
    

    覆盖命令

    可以在容器创建时对命令进行覆盖,可以看到这里覆盖了根命令执行了自定义命令
    [root@vm1 cmd]# docker run cmd:v1 ls /
    bin
    dev
    etc
    home
    proc
    root
    sys
    tmp
    usr
    var
    [root@vm1 cmd]# docker run cmd:v1 free -g
               total        used        free      shared  buff/cache   available
    Mem:              4           2           1           0           1           2
    Swap:             0           0           0
    [root@vm1 cmd]#
    

ENTRYPOINT

默认命令

假设针对如下Dockerfile

FROM busybox
WORKDIR /home/data
RUN touch test.txt
ENTRYPOINT ls /home/data

执行镜像构建并运行,执行默认命令

[root@vm1 entrypoint]# docker build . -t entrypoint:v1
[root@vm1 entrypoint]# docker run entrypoint:v1
test.txt
[root@vm1 entrypoint]#

追加命令

可以在容器创建时对命令无法进行覆盖,是对命令进行追加

[root@vm1 entrypoint]# docker run entrypoint:v1 ls / #
test.txt
[root@vm1 entrypoint]# 
[root@vm1 entrypoint]# docker run entrypoint:v1 && ls /
test.txt
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@vm1 entrypoint]# 
[root@vm1 entrypoint]# docker run entrypoint:v1 && free -g
test.txt
              total        used        free      shared  buff/cache   available
Mem:              3           1           0           0           1           1
Swap:             0           0           0
[root@vm1 entrypoint]#

覆盖命令

如果想对命令进行覆盖可以使用如下方式

[root@vm1 entrypoint]# docker run --entrypoint=ls  entrypoint:v1 /home
data
[root@vm1 entrypoint]# 
[root@vm1 entrypoint]# docker run --entrypoint=free  entrypoint:v1 -g
              total        used        free      shared  buff/cache   available
Mem:              4           2           1           0           1           2
Swap:             0           0           0
[root@vm1 entrypoint]#

—entrypoint指定目标命令,命令最后指定参数

命令对比

最佳实践

ENTRYPOINT用来写一个容器固定的指令,CMD用来写默认参数。
当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令
换句话说实际执行时,会变成

FROM busybox
WORKDIR /home/data
RUN touch test.txt
ENTRYPOINT ls
CMD -l

构建并运行,步骤如下

[root@vm1 xx]# docker run xx:v1
test.txt
[root@vm1 xx]# docker build . -t xx:v1
[root@vm1 xx]# docker run xx:v1 -al
test.txt
[root@vm1 xx]#

固定指令ENTRYPOINT使用—entrypoint也是可以替换的。