What is the difference between CMD and ENTRYPOINT in a Dockerfile?

前端 未结 16 1738
自闭症患者
自闭症患者 2020-11-21 22:31

In Dockerfiles there are two commands that look similar to me: CMD and ENTRYPOINT. But I guess that there is a (subtle?) difference between them -

相关标签:
16条回答
  • 2020-11-21 23:10

    According to docker docs,

    Both CMD and ENTRYPOINT instructions define what command gets executed when running a container. There are few rules that describe their co-operation.

    1. Dockerfile should specify at least one of CMD or ENTRYPOINT commands.
    2. ENTRYPOINT should be defined when using the container as an executable.
    3. CMD should be used as a way of defining default arguments for an ENTRYPOINT command or for executing an ad-hoc command in a container.
    4. CMD will be overridden when running the container with alternative arguments.

    The tables below shows what command is executed for different ENTRYPOINT / CMD combinations:

    -- 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  ║
    ╚════════════════════════════╩═════════════════════════════════════════════════╝
    
    0 讨论(0)
  • 2020-11-21 23:12

    Yes, that is a good question. I don't understand it fully yet, but:

    I understand that ENTRYPOINT is the binary that is being executed. You can overide entrypoint by --entrypoint="".

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

    CMD is the default argument to container. Without entrypoint, default argument is command that is executed. With entrypoint, cmd is passed to entrypoint as argument. You can emulate a command with entrypoint.

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

    So, main advantage is that with entrypoint you can pass arguments (cmd) to your container. To accomplish this, you need to use both:

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

    and

    docker build -t=cat .
    

    then you can use:

    docker run cat /etc/passwd
    #              ^^^^^^^^^^^
    #                   CMD
    #          ^^^      
    #          image (tag)- using the default ENTRYPOINT
    
    0 讨论(0)
  • 2020-11-21 23:14

    Comments on EntryPoint function in code

    // ENTRYPOINT /usr/sbin/nginx.

    // Set the entrypoint (which defaults to sh -c) to /usr/sbin/nginx.

    // Will accept the CMD as the arguments to /usr/sbin/nginx.

    Another reference from documents

    You can use the exec form of ENTRYPOINT to set fairly stable default commands and arguments and then use CMD to set additional defaults that are more likely to be changed.

    Example:

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

    Build: 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
    

    p.s: In presence of EntryPoint, CMD will hold arguments to fed to EntryPoint. In absense of EntryPoint, CMD will be the command which will be run.

    0 讨论(0)
  • 2020-11-21 23:15

    The ENTRYPOINT specifies a command that will always be executed when the container starts.

    The CMD specifies arguments that will be fed to the ENTRYPOINT.

    If you want to make an image dedicated to a specific command you will use ENTRYPOINT ["/path/dedicated_command"]

    Otherwise, if you want to make an image for general purpose, you can leave ENTRYPOINT unspecified and use CMD ["/path/dedicated_command"] as you will be able to override the setting by supplying arguments to docker run.

    For example, if your Dockerfile is:

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

    Running the image without any argument will ping the 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
    

    Now, running the image with an argument will ping the argument:

    $ 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
    

    For comparison, if your Dockerfile is:

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

    Running the image without any argument will ping the 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
    

    But running the image with an argument will run the argument:

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

    See this article from Brian DeHamer for even more details: https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/

    0 讨论(0)
  • 2020-11-21 23:16

    In a nutshell:

    • CMD sets default command and/or parameters, which can be overwritten from command line when docker container runs.
    • ENTRYPOINT command and parameters will not be overwritten from command line. Instead, all command line arguments will be added after ENTRYPOINT parameters.

    If you need more details or would like to see difference on example, there is a blog post that comprehensively compare CMD and ENTRYPOINT with lots of examples - http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/

    0 讨论(0)
  • 2020-11-21 23:16

    Most people explain it perfectly here, so I won't repeat all the answers. But to get a good feeling I would suggest testing it yourself by looking at the processes in the container.

    Create a tiny Dockerfile of the form:

    FROM ubuntu:latest
    CMD /bin/bash
    

    Build it, run it in with docker run -it theimage and run ps -eo ppid,pid,args in the container. Compare this output to the output you receive from ps when using:

    • docker run -it theimage bash
    • Rebuilding the image but with ENTRYPOINT /bin/bash and running it in both ways
    • Using CMD ["/bin/bash"]
    • ...

    This way you will easily see the differences between all possible methods for yourself.

    0 讨论(0)
提交回复
热议问题