Dockerfile中CMD和ENTRYPOINT有什么区别?

 霸道Q丫头 发布于 2023-01-29 14:38

在Dockerfiles中有两个看起来与我类似的命令:CMDENTRYPOINT.但是我猜它们之间存在着一种(微妙的?)差异 - 否则对于同样的事情来说两个命令就没有任何意义.

文档说明了 CMD

CMD的主要目的是为执行容器提供默认值.

并为ENTRYPOINT:

ENTRYPOINT可帮助您配置可作为可执行文件运行的容器.

那么,这两个命令之间的区别是什么?

9 个回答
  • 简而言之:

    CMD设置默认命令和/或参数,当docker容器运行时,可以从命令行覆盖这些命令和/或参数.

    ENTRYPOINT命令和参数不会从命令行覆盖.相反,所有命令行参数将在ENTRYPOINT参数之后添加.

    如果您需要更多详细信息或想在示例中看到差异,可以通过大量示例全面比较CMD和ENTRYPOINT的博客文章 - http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/

    2023-01-29 14:40 回答
  • ENTRYPOINT规定将始终容器启动时执行的命令.

    CMD指定参数,将被输送到ENTRYPOINT.

    如果您想制作专用于您将使用的特定命令的图像 ENTRYPOINT ["/path/dedicated_command"]

    否则,如果您想为一般目的制作图像,您可以保留ENTRYPOINT未指定并使用,CMD ["/path/dedicated_command"]因为您可以通过提供参数来覆盖设置docker run.

    例如,如果您的Dockerfile是:

    FROM debian:wheezy
    ENTRYPOINT ["/bin/ping"]
    CMD ["localhost"]
    

    不带任何参数运行映像将ping localhost:

    $ docker run -it test
    PING localhost (127.0.0.1): 48 data bytes
    56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.096 ms
    56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.088 ms
    56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.088 ms
    ^C--- localhost ping statistics ---
    3 packets transmitted, 3 packets received, 0% packet loss
    round-trip min/avg/max/stddev = 0.088/0.091/0.096/0.000 ms
    

    现在,使用参数运行图像将ping参数:

    $ docker run -it test google.com
    PING google.com (173.194.45.70): 48 data bytes
    56 bytes from 173.194.45.70: icmp_seq=0 ttl=55 time=32.583 ms
    56 bytes from 173.194.45.70: icmp_seq=2 ttl=55 time=30.327 ms
    56 bytes from 173.194.45.70: icmp_seq=4 ttl=55 time=46.379 ms
    ^C--- google.com ping statistics ---
    5 packets transmitted, 3 packets received, 40% packet loss
    round-trip min/avg/max/stddev = 30.327/36.430/46.379/7.095 ms
    

    为了比较,如果您的Dockerfile是:

    FROM debian:wheezy
    CMD ["/bin/ping", "localhost"]
    

    不带任何参数运行映像将ping localhost:

    $ docker run -it test
    PING localhost (127.0.0.1): 48 data bytes
    56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.076 ms
    56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.087 ms
    56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
    ^C--- localhost ping statistics ---
    3 packets transmitted, 3 packets received, 0% packet loss
    round-trip min/avg/max/stddev = 0.076/0.084/0.090/0.000 ms
    

    但是使用参数运行图像将运行参数:

    docker run -it test bash
    root@e8bb7249b843:/#
    

    有关更多详细信息,请参阅Brian DeHamer的这篇文章:https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/

    2023-01-29 14:40 回答
  • 直觉 CMD和ENTRYPOINT之间的区别:

    ENTRYPOINT:容器启动时运行的命令.

    CMD:在容器启动时运行的命令或ENTRYPOINT的参数(如果已指定).

    是的,它正在混淆.

    运行docker run时,您可以覆盖其中的任何一个.

    CMD和ENTRYPOINT之间的区别:

    docker run -it --rm yourcontainer /bin/bash            <-- /bin/bash overrides CMD
                                                           <-- /bin/bash does not override ENTRYPOINT
    docker run -it --rm --entrypoint ls yourcontainer      <-- overrides ENTRYPOINT with ls
    docker run -it --rm --entrypoint ls yourcontainer  -la  <-- overrides ENTRYPOINT with ls and overrides CMD with -la
    

    更多关于CMD和之间的区别ENTRYPOINT:

    参数docker run例如/ bin/bash的覆盖我们Dockerfile写任何CMD命令.

    使用常规命令(例如)时,无法在运行时覆盖ENTRYPOINT docker run [args].所述args在端部docker run [args]被设置为参数入口点.通过这种方式,我们可以创建一个container像普通二进制文件一样的东西ls.

    所以CMD可以作为ENTRYPOINT的默认参数,然后我们可以从[args]覆盖CMD args.

    ENTRYPOINT可以覆盖--entrypoint.

    2023-01-29 14:40 回答
  • 是的,这是个好问题.我还不完全理解它,但是:

    我知道这ENTRYPOINT是正在执行的二进制文件.您可以通过--entrypoint =""覆盖入口点.

    docker run -t -i --entrypoint="/bin/bash" ubuntu
    

    CMD是容器的默认参数.如果没有入口点,则default参数是执行的命令.使用入口点,cmd作为参数传递给入口点.您可以使用入口点模拟命令.

    # no entrypoint
    docker run ubuntu /bin/cat /etc/passwd
    
    # with entry point, emulating cat command
    docker run --entrypoint="/bin/cat" ubuntu /etc/passwd
    

    因此,主要优点是使用入口点可以将参数(cmd)传递给容器.要实现此目的,您需要同时使用:

    # Dockerfile
    FROM ubuntu
    ENTRYPOINT ["/bin/cat"]
    

    docker build -t=cat .
    

    然后你可以使用:

    docker run cat /etc/passwd
    #              ^^^^^^^^^^^
    #                   CMD
    #          ^^^      
    #          image (tag)- using the default ENTRYPOINT
    

    2023-01-29 14:40 回答
  • 据docker docs说,

    CMD和ENTRYPOINT指令都定义了在运行容器时执行的命令.很少有规则描述他们的合作.

      Dockerfile应至少指定一个CMD或多个ENTRYPOINT命令.

      ENTRYPOINT 应该在将容器用作可执行文件时定义.

      CMD应该用作定义ENTRYPOINT命令的默认参数或在容器中执行ad-hoc命令的方法.

      CMD 在使用备用参数运行容器时将覆盖.

    下表显示了针对不同ENTRYPOINT/ CMD组合执行的命令:

    - No ENTRYPOINT

    ????????????????????????????????????????????????????????????
    ? No CMD                     ? error, not allowed          ?
    ????????????????????????????????????????????????????????????
    ? CMD [“exec_cmd”, “p1_cmd”] ? exec_cmd p1_cmd             ?
    ????????????????????????????????????????????????????????????
    ? CMD [“p1_cmd”, “p2_cmd”]   ? p1_cmd p2_cmd               ?
    ????????????????????????????????????????????????????????????
    ? CMD exec_cmd p1_cmd        ? /bin/sh -c exec_cmd p1_cmd  ?
    ????????????????????????????????????????????????????????????
    

    - ENTRYPOINT exec_entry p1_entry

    ?????????????????????????????????????????????????????????????????
    ? No CMD                     ? /bin/sh -c exec_entry p1_entry   ?
    ?????????????????????????????????????????????????????????????????
    ? CMD [“exec_cmd”, “p1_cmd”] ? /bin/sh -c exec_entry p1_entry   ?
    ?????????????????????????????????????????????????????????????????
    ? CMD [“p1_cmd”, “p2_cmd”]   ? /bin/sh -c exec_entry p1_entry   ?
    ?????????????????????????????????????????????????????????????????
    ? CMD exec_cmd p1_cmd        ? /bin/sh -c exec_entry p1_entry   ?
    ?????????????????????????????????????????????????????????????????
    

    - ENTRYPOINT [“exec_entry”, “p1_entry”]

    ????????????????????????????????????????????????????????????????????????????????
    ? No CMD                     ? exec_entry p1_entry                             ?
    ????????????????????????????????????????????????????????????????????????????????
    ? CMD [“exec_cmd”, “p1_cmd”] ? exec_entry p1_entry exec_cmd p1_cmd             ?
    ????????????????????????????????????????????????????????????????????????????????
    ? CMD [“p1_cmd”, “p2_cmd”]   ? exec_entry p1_entry p1_cmd p2_cmd               ?
    ????????????????????????????????????????????????????????????????????????????????
    ? CMD exec_cmd p1_cmd        ? exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd  ?
    ????????????????????????????????????????????????????????????????????????????????
    

    2023-01-29 14:40 回答
  • 对代码中的 EntryPoint函数的评论

    // ENTRYPOINT/usr/sbin/nginx.

    //将入口点(默认为sh -c)设置为/ usr/sbin/nginx.

    //将接受CMD作为/ usr/sbin/nginx的参数.

    文件的另一个参考

    您可以使用ENTRYPOINT的exec形式设置相当稳定的默认命令和参数,然后使用CMD设置更可能更改的其他默认值.

    例:

    FROM ubuntu:14.04.3
    ENTRYPOINT ["/bin/ping"]
    CMD ["localhost", "-c", "2"]
    

    构建:sudo docker build -t ent_cmd.

    CMD arguments are easy to override.
    
    NO argument (sudo docker -it ent_cmd)                :  ping localhost 
    argument    (sudo docker run -it ent_cmd google.com) :  ping google.com
    

    .

    To override EntryPoint argument, you need to supply entrypoint
    sudo docker run -it --entrypoint="/bin/bash" ent_cmdd
    

    ps:在EntryPoint存在的情况下,CMD将保留参与EntryPoint的参数.在没有EntryPoint的情况下,CMD将成为将要运行的命令.

    2023-01-29 14:41 回答
  • Docker有一个默认入口点,/bin/sh -c但它没有默认命令.

    当您像这样运行docker时: docker run -i -t ubuntu bash 入口点是默认值/bin/sh -c,图像是ubuntu,命令是bash.

    该命令通过入口点运行.即,实际执行的事情是/bin/sh -c bash.这使得Docker可以RUN依靠shell的解析器快速实现.

    后来,人们要求能够自定义这个,所以ENTRYPOINT并且--entrypoint被介绍了.

    ubuntu上面示例中的所有内容都是命令,并传递给入口点.使用该CMD指令时,就像您正在做的那样docker run -i -t ubuntu <cmd>.<cmd>将是入口点的参数.

    如果您改为输入此命令,也会得到相同的结果docker run -i -t ubuntu.你仍然会在容器中启动一个bash shell,因为ubuntu Dockerfile指定了一个默认的CMD:CMD ["bash"]

    当所有内容都传递到入口点时,您可以从图像中获得非常好的行为.@Jiri示例很好,它显示了如何将图像用作"二进制".当["/bin/cat"]用作入口点然后做docker run img /etc/passwd,你得到它,/etc/passwd是命令并传递给入口点,因此最终结果执行就是这样/bin/cat /etc/passwd.

    另一个例子是将任何cli作为入口点.例如,如果你有一个redis图像,而不是运行docker run redisimg redis -H something -u toto get key,你可以简单地运行,ENTRYPOINT ["redis", "-H", "something", "-u", "toto"]然后像这样运行相同的结果:docker run redisimg get key.

    2023-01-29 14:41 回答
  • 我将以示例1的方​​式添加答案,这可能有助于您更好地理解差异。

    假设我们要创建一个在启动时始终运行sleep命令的映像。我们将创建自己的图像并指定一个新命令:

    FROM ubuntu
    CMD sleep 10
    

    现在,我们构建图像:

    docker build -t custom_sleep .
    docker run custom_sleep
    # sleeps for 10 seconds and exits
    

    如果要更改秒数怎么办?我们将不得不更改Dockerfile值,因为该值在此处进行了硬编码,或者通过提供不同的值来覆盖该命令:

    docker run custom_sleep sleep 20
    

    尽管这可行,但这不是一个好的解决方案,因为我们有一个多余的“ sleep”命令(容器的目的是sleep,因此必须显式指定该sleep命令不是一个好习惯)。

    现在让我们尝试使用以下ENTRYPOINT指令:

    docker build -t custom_sleep .
    docker run custom_sleep
    # sleeps for 10 seconds and exits
    

    该指令指定在容器启动时将运行的程序

    现在我们可以运行:

    docker run custom_sleep sleep 20
    

    那么默认值呢?好吧,你猜对了:

    FROM ubuntu
    ENTRYPOINT sleep
    

    ENTRYPOINT是将要运行的程序,并通过在容器上的值将被附加到它。

    ENTRYPOINT可通过指定覆盖--entrypoint标志,后面是要使用新的切入点。

    不是我的,我曾经看过提供此示例的教程

    2023-01-29 14:41 回答
  • 接受的答案很棒,可以解释历史.我发现这个表格从官方文档"CMD和ENTRYPOINT如何互动"中解释得非常好: 在此输入图像描述

    2023-01-29 14:41 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有