美文网首页Docker
【现学现忘Docker基础】— 30.CMD和ENTRYPOIN

【现学现忘Docker基础】— 30.CMD和ENTRYPOIN

作者: 繁华似锦Fighting | 来源:发表于2021-04-19 00:36 被阅读0次

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

    1、CMD指令和ENTRYPOINT指令说明

    CMD指令, 支持三种格式:

    CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
     
    CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
     
    CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
    

    每个Dockerfile只能生效一条CMD指令。如果指定了多条CMD指令,只有最后一条生效。

    如果用户启动容器时候指定了运行的命令,则会覆盖掉CMD指定的命令。

    ENTRYPOINT指令,支持两种格式:

    ENTRYPOINT ["executable", "param1", "param2"]
    
    ENTRYPOINT command param1 param2(shell中执行)。
    

    每个Dockerfile中只能生效一个ENTRYPOINT指令,当有多个ENTRYPOINT指令时,只有最后一个起效。

    如果用户启动容器时候指定了运行的命令,不会被docker run执行的命令参数覆盖。(追加效果:docker run命令之后的参数,会被当做参数传递给ENTRYPOINT,之后形成新的命令组合)

    2、CMD指令只有最后一条生效的原因

    CMD指令是一个容器的默认的可执行命令。也就是容器启动以后,默认执行的命令。(默认是重点)

    换句话说,给出了CMD指令的一个角色定位,它主要作用是定义默认的容器启动后执行的命令

    提示:

    这也就是网上所说,只有最后一条CMD指令会生效,之前的都会被覆盖掉。

    就是因为CMD指令的角色定位就是默认,如果你不进行额外指定,那么就执行CMD指令。否则,你要自己指定了命令,那么就不会执行CMD指令,这也就是相当于CMD指令会被覆盖。

    而ENTRYPOINT指令,才是正统地用于定义容器启动以后的执行体,从名字上我们也可以看出,entrypoint 入口点的意思,一个容器的“入口”。

    3、CMD指令演示

    我们以contos镜像为基础,对该镜像进行修改。

    (1)准备测试环境

    进入宿主机/home/mydockerfile目录中,创建Dockerfil文件Dockerfile_cmd

    # mydockerfile目录中创建Dockerfile_cmd文件
    [root@192 mydockerfile]# pwd
    /home/mydockerfile
    [root@192 mydockerfile]# touch Dockerfile_cmd
    

    编辑Dockerfile_cmd文件,内容如下:

    FROM centos # 继承了本地的centos镜像
    CMD ["ls","-a"] # 执行ls -a 命令
    

    说明:我们之前CMD执行都是/bin/bash,这回改成ls -a命令是一样的,就是启动容器后执行ls -a命令。

    根据Dockerfile_cmd生成cmd镜像。

    [root@192 mydockerfile]# docker build -f /home/mydockerfile/Dockerfile_cmd -t wukong/cmd:1.0 .
    Sending build context to Docker daemon  3.072kB
    Step 1/2 : FROM centos
     ---> 300e315adb2f
    Step 2/2 : CMD ["ls","-a"]
     ---> Running in e34a0fc14329
    Removing intermediate container e34a0fc14329
     ---> de211d4ca7f3
    Successfully built de211d4ca7f3
    Successfully tagged wukong/cmd:1.0
    

    (2)进行验证

    运行wukong/cmd镜像,查看结果。

    # 查看本地Docker镜像
    [root@192 mydockerfile]# docker images
    REPOSITORY      TAG       IMAGE ID       CREATED         SIZE
    wukong/cmd      1.0       de211d4ca7f3   2 minutes ago   209MB
    wokong_centos   1.6       6441f63090d4   3 hours ago     291MB
    centos          latest    300e315adb2f   3 months ago    209MB
    
    # 直接运行该容器,查看结果,输出了默认工作目录中的内容。
    [root@192 mydockerfile]# docker run wukong/cmd:1.0 
    .
    ..
    .dockerenv
    bin
    dev
    etc
    home
    lib
    lib64
    lost+found
    media
    mnt
    opt
    proc
    root
    run
    sbin
    srv
    sys
    tmp
    usr
    var
    
    # 容器启动,执行完ls -a 命令后,就会停止。
    [root@192 mydockerfile]# docker ps
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    
    

    接下来,我们在docker run命令后,加入-l命令,我们再来查看一下结果。

    [root@192 mydockerfile]# docker run wukong/cmd:1.0 -l
    docker: Error response from daemon: OCI runtime create failed: container_linux.go:367: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
    

    说明:

    我的意思是想追加一个-l参数,让容器启动后,执行ls -al命令。结果我们看到是,可执行文件找不到的报错,exec: "-l":executable file not found

    这就是我们之前说过的,跟在镜像名后面的是command(命令),运行时会替换CMD的默认值。也就是-l参数替换了Dockerfile文件中的CMD ["ls","-a"]命令,而不是添加在原来的命令里。

    而单独的-l参数不是Linux命令,不能单独的命令,自然找不到,所以就报错了。

    所以综上所述,CMD指令会被docker run之后的参数替换。

    那么如果我们希望加入-i这个参数,就必须重新完整的输入整个命令,如下:

    [root@192 mydockerfile]# docker run wukong/cmd:1.0 ls -al
    total 0
    drwxr-xr-x.   1 root root   6 Mar 20 11:13 .
    drwxr-xr-x.   1 root root   6 Mar 20 11:13 ..
    -rwxr-xr-x.   1 root root   0 Mar 20 11:13 .dockerenv
    lrwxrwxrwx.   1 root root   7 Nov  3 15:22 bin -> usr/bin
    drwxr-xr-x.   5 root root 340 Mar 20 11:13 dev
    drwxr-xr-x.   1 root root  66 Mar 20 11:13 etc
    drwxr-xr-x.   2 root root   6 Nov  3 15:22 home
    lrwxrwxrwx.   1 root root   7 Nov  3 15:22 lib -> usr/lib
    lrwxrwxrwx.   1 root root   9 Nov  3 15:22 lib64 -> usr/lib64
    drwx------.   2 root root   6 Dec  4 17:37 lost+found
    drwxr-xr-x.   2 root root   6 Nov  3 15:22 media
    drwxr-xr-x.   2 root root   6 Nov  3 15:22 mnt
    drwxr-xr-x.   2 root root   6 Nov  3 15:22 opt
    dr-xr-xr-x. 122 root root   0 Mar 20 11:13 proc
    dr-xr-x---.   2 root root 162 Dec  4 17:37 root
    drwxr-xr-x.  11 root root 163 Dec  4 17:37 run
    lrwxrwxrwx.   1 root root   8 Nov  3 15:22 sbin -> usr/sbin
    drwxr-xr-x.   2 root root   6 Nov  3 15:22 srv
    dr-xr-xr-x.  13 root root   0 Mar 20 06:42 sys
    drwxrwxrwt.   7 root root 145 Dec  4 17:37 tmp
    drwxr-xr-x.  12 root root 144 Dec  4 17:37 usr
    drwxr-xr-x.  20 root root 262 Dec  4 17:37 var
    

    4、ENTRYPOINT指令演示

    通过上面CMD指令演示相似。

    我们以contos镜像为基础,对该镜像进行修改。

    (1)准备测试环境

    进入宿主机/home/mydockerfile目录中,创建Dockerfil文件Dockerfile_entrypoint

    # mydockerfile目录中创建Dockerfile_entrypoint文件
    [root@192 mydockerfile]# pwd
    /home/mydockerfile
    [root@192 mydockerfile]# touch Dockerfile_entrypoint
    

    编辑Dockerfile_entrypoint文件,内容如下:

    FROM centos # 继承了本地的centos镜像
    ENTRYPOINT ["ls","-a"] # 执行ls -a 命令
    

    根据Dockerfile_entrypoint生成entrypoint镜像。

    [root@192 mydockerfile]# docker build -f /home/mydockerfile/Dockerfile_entrypoint -t wukong/entrypoint:1.0 .
    Sending build context to Docker daemon  4.096kB
    Step 1/2 : FROM centos
     ---> 300e315adb2f
    Step 2/2 : ENTRYPOINT ["ls","-a"]
     ---> Running in ecd4a636d8be
    Removing intermediate container ecd4a636d8be
     ---> e641401b4ea5
    Successfully built e641401b4ea5
    Successfully tagged wukong/entrypoint:1.0
    

    (2)进行验证

    运行wukong/entrypoint镜像,查看结果。

    # 查看本地Docker镜像
    [root@192 mydockerfile]# docker images
    REPOSITORY          TAG       IMAGE ID       CREATED         SIZE
    wukong/entrypoint   1.0       e641401b4ea5   2 minutes ago   209MB
    wukong/cmd          1.0       adda4543a402   3 minutes ago   209MB
    wokong_centos       1.6       6441f63090d4   4 hours ago     291MB
    centos              latest    300e315adb2f   3 months ago    209MB
    
    # 直接运行该容器,查看结果,输出了默认工作目录中的内容。
    [root@192 mydockerfile]# docker run wukong/entrypoint:1.0 
    .
    ..
    .dockerenv
    bin
    dev
    etc
    home
    lib
    lib64
    lost+found
    media
    mnt
    opt
    proc
    root
    run
    sbin
    srv
    sys
    tmp
    usr
    var
    

    接下来,我们在docker run命令后,加入-l命令,我们再来查看一下结果。

    [root@192 mydockerfile]# docker run wukong/entrypoint:1.0 -l
    total 0
    drwxr-xr-x.   1 root root   6 Mar 20 12:03 .
    drwxr-xr-x.   1 root root   6 Mar 20 12:03 ..
    -rwxr-xr-x.   1 root root   0 Mar 20 12:03 .dockerenv
    lrwxrwxrwx.   1 root root   7 Nov  3 15:22 bin -> usr/bin
    drwxr-xr-x.   5 root root 340 Mar 20 12:03 dev
    drwxr-xr-x.   1 root root  66 Mar 20 12:03 etc
    drwxr-xr-x.   2 root root   6 Nov  3 15:22 home
    lrwxrwxrwx.   1 root root   7 Nov  3 15:22 lib -> usr/lib
    lrwxrwxrwx.   1 root root   9 Nov  3 15:22 lib64 -> usr/lib64
    drwx------.   2 root root   6 Dec  4 17:37 lost+found
    drwxr-xr-x.   2 root root   6 Nov  3 15:22 media
    drwxr-xr-x.   2 root root   6 Nov  3 15:22 mnt
    drwxr-xr-x.   2 root root   6 Nov  3 15:22 opt
    dr-xr-xr-x. 124 root root   0 Mar 20 12:03 proc
    dr-xr-x---.   2 root root 162 Dec  4 17:37 root
    drwxr-xr-x.  11 root root 163 Dec  4 17:37 run
    lrwxrwxrwx.   1 root root   8 Nov  3 15:22 sbin -> usr/sbin
    drwxr-xr-x.   2 root root   6 Nov  3 15:22 srv
    dr-xr-xr-x.  13 root root   0 Mar 20 06:42 sys
    drwxrwxrwt.   7 root root 145 Dec  4 17:37 tmp
    drwxr-xr-x.  12 root root 144 Dec  4 17:37 usr
    drwxr-xr-x.  20 root root 262 Dec  4 17:37 var
    

    说明:想给Dockerfile文件中的ENTRYPOINT ["ls","-a"]命令追加一个-l参数,让容器启动后执行ls -al命令,结果顺利执行。

    结论:这就说明了,ENTRYPOINT指令是可以在容器启动的时候追加命令。

    Dockerfile中很多命令的功能都十分的相似,我们需要了解它们的区别,我们最好的学习就是对比他们,然后测试效果。

    以上就是CMD指令和ENTRYPOINT指令的区别。

    相关文章

      网友评论

        本文标题:【现学现忘Docker基础】— 30.CMD和ENTRYPOIN

        本文链接:https://www.haomeiwen.com/subject/jtincltx.html