ENTRYPOINT

参考:ENTRYPOINT

EXTRYPOING指令指定容器启动后运行的可执行文件

语法

2种书写格式:

  1. ENTRYPOINT ["executable", "param1", "param2"]exec形式,推荐)
  2. ENTRYPOINT command param1 param2shell形式)

可以在使用docker run命令启动容器时添加executable参数,

Dockerfile文件中只有最后一条ENTRYPOINT指令其作用

Exec形式示例

FROM zjzstu/ubuntu:18.04
ENTRYPOINT ["top", "-b"]
CMD ["-c"]

完整的入口点命令为top -b -c。启动该容器后,仅有该应用运行

启动容器如下:

# 镜像名为top:v4
$ docker run -it --rm --name test top:v4
top - 06:01:45 up  4:26,  0 users,  load average: 0.20, 0.38, 0.37
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.7 us,  0.5 sy,  0.0 ni, 97.6 id,  0.1 wa,  0.0 hi,  0.1 si,  0.0 st
KiB Mem : 16164188 total,  8438760 free,  3265344 used,  4460084 buff/cache
KiB Swap: 15999996 total, 15999996 free,        0 used. 11943604 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
    1 root      20   0   36484   3036   2688 R   0.0  0.0   0:00.21 top

也可通过docker exec验证

$ docker exec fde5 ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.4  0.0  36484  3020 pts/0    Ss+  06:05   0:00 top -b
root        11  0.0  0.0  34400  2860 ?        Rs   06:06   0:00 ps aux

注意 1:exec形式作为JSON数组,使用双引号而不是单引号

注意 2:exec形式不会调用命令行shell,所以如果要进行shell处理必须显式调用/bin/sh -c,比如ENTRYPOING ["sh", "-c", "echo $HOME"]

Shell形式示例

shell形式的缺点在于其作为/bin/sh -c的子命令,不会输入信号。这意味着可执行文件不是容器的PID 1,不会接收到Unix信号,所以可执行文件无法接受来自docker stop <container>SIGTERM信号。此时运行docker stop,容器不会干净地退出,stop命令将在超时后强制发送SIGKILL指令

可以指定exec启动命令,这样就能得到PID 1的入口程序

FROM zjzstu/ubuntu:18.04
ENTRYPOINT exec top -b

创建镜像top并启动

$ docker run -t top .

$ docker run -it --rm --name test top
top - 06:17:18 up  4:41,  0 users,  load average: 0.43, 0.65, 0.54
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.8 us,  0.5 sy,  0.0 ni, 97.5 id,  0.1 wa,  0.0 hi,  0.1 si,  0.0 st
KiB Mem : 16164188 total,  8468692 free,  3225808 used,  4469688 buff/cache
KiB Swap: 15999996 total, 15999996 free,        0 used. 11979700 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
    1 root      20   0   36484   2956   2604 R   0.0  0.0   0:00.21 top

可使用/usr/bin/time测试docker top停止镜像的运行时间

对于镜像top,测试如下

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
dc47139817b3        top                 "/bin/sh -c 'exec to…"   2 minutes ago       Up 2 minutes                            test
(base) zj@zj-ThinkPad-T470p:~$ /usr/bin/time docker stop dc47
dc47
0.01user 0.02system 0:00.52elapsed 7%CPU (0avgtext+0avgdata 63500maxresident)k
0inputs+0outputs (0major+7827minor)pagefaults 0swaps

对于不使用exec命令的Shell形式,测试如下:

$ /usr/bin/time docker stop f5fe
f5fe
0.01user 0.02system 0:10.68elapsed 0%CPU (0avgtext+0avgdata 62684maxresident)k
0inputs+0outputs (0major+7923minor)pagefaults 0swaps

前者花费了0.52秒,后者花费了10.68

CMD和ENTRYPOINT的交互

CMDENTRYPOINT指令都定义了运行容器时执行的命令,其合作如下:

  1. Dockerfile文件应该至少定义一条CMDENTRYPOINT指令
  2. ENTRYPOING适用于将容器作为可执行文件的场景
  3. CMD适用于定义ENTRYPOINT命令在容器中执行特殊命令的默认参数
  4. 使用可选参数运行容器时,将重写CMD

注意:如果CMD指令定义在基础镜像,那么ENTRYPOINT将会重置CMD为空。如果需要CMD指令操作,必须在当前镜像上重写