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

前端 未结 16 1740
自闭症患者
自闭症患者 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:17

    The accepted answer is fabulous in explaining the history. I find this table explain it very well from official doc on 'how CMD and ENTRYPOINT interact':

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

    • A Dockerfile should specify at least one CMD or ENTRYPOINT instruction

    • Only the last CMD and ENTRYPOINT in a Dockerfile will be used

    • ENTRYPOINT should be defined when using the container as an executable

    • You should use the CMD instruction as a way of defining default arguments for the command defined as ENTRYPOINT or for executing an ad-hoc command in a container

    • CMD will be overridden when running the container with alternative arguments

    • ENTRYPOINT sets the concrete default application that is used every time a container is created using the image

    • If you couple ENTRYPOINT with CMD, you can remove an executable from CMD and just leave its arguments which will be passed to ENTRYPOINT

    • The best use for ENTRYPOINT is to set the image's main command, allowing that image to be run as though it was that command (and then use CMD as the default flags)

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

    Difference between CMD and ENTRYPOINT by intuition:

    • ENTRYPOINT: command to run when container starts.
    • CMD: command to run when container starts or arguments to ENTRYPOINT if specified.

    Yes, it's mixing up.

    You can override any of them when running docker run.

    Difference between CMD and ENTRYPOINT by example:

    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
    

    More on difference between CMD and ENTRYPOINT:

    Argument to docker run such as /bin/bash overrides any CMD command we wrote in Dockerfile.

    ENTRYPOINT cannot be overriden at run time with normal commands such as docker run [args]. The args at the end of docker run [args] are provided as arguments to ENTRYPOINT. In this way we can create a container which is like a normal binary such as ls.

    So CMD can act as default parameters to ENTRYPOINT and then we can override the CMD args from [args].

    ENTRYPOINT can be overriden with --entrypoint.

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

    I'll add my answer as an example1 that might help you better understand the difference.

    Let's suppose we want to create an image that will always run a sleep command when it starts. We'll create our own image and specify a new command:

    FROM ubuntu
    CMD sleep 10
    

    Building the image:

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

    What if we want to change the number of seconds? We would have to change the Dockerfile since the value is hardcoded there, or override the command by providing a different one:

    docker run custom_sleep sleep 20
    

    While this works, it's not a good solution, as we have a redundant "sleep" command. Why redundant? Because the container's only purpose is to sleep, so having to specify the sleep command explicitly is a bit awkward.

    Now let's try using the ENTRYPOINT instruction:

    FROM ubuntu
    ENTRYPOINT sleep
    

    This instruction specifies the program that will be run when the container starts.

    Now we can run:

    docker run custom_sleep 20
    

    What about a default value? Well, you guessed it right:

    FROM ubuntu
    ENTRYPOINT ["sleep"]
    CMD ["10"]
    

    The ENTRYPOINT is the program that will be run, and the value passed to the container will be appended to it.

    The ENTRYPOINT can be overridden by specifying an --entrypoint flag, followed by the new entry point you want to use.

    Not mine, I once watched a tutorial that provided this example

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

    Docker has a default entrypoint which is /bin/sh -c but does not have a default command.

    When you run docker like this: docker run -i -t ubuntu bash the entrypoint is the default /bin/sh -c, the image is ubuntu and the command is bash.

    The command is run via the entrypoint. i.e., the actual thing that gets executed is /bin/sh -c bash. This allowed Docker to implement RUN quickly by relying on the shell's parser.

    Later on, people asked to be able to customize this, so ENTRYPOINT and --entrypoint were introduced.

    Everything after ubuntu in the example above is the command and is passed to the entrypoint. When using the CMD instruction, it is exactly as if you were doing docker run -i -t ubuntu <cmd>. <cmd> will be the parameter of the entrypoint.

    You will also get the same result if you instead type this command docker run -i -t ubuntu. You will still start a bash shell in the container because of the ubuntu Dockerfile specified a default CMD: CMD ["bash"]

    As everything is passed to the entrypoint, you can have a very nice behavior from your images. @Jiri example is good, it shows how to use an image as a "binary". When using ["/bin/cat"] as entrypoint and then doing docker run img /etc/passwd, you get it, /etc/passwd is the command and is passed to the entrypoint so the end result execution is simply /bin/cat /etc/passwd.

    Another example would be to have any cli as entrypoint. For instance, if you have a redis image, instead of running docker run redisimg redis -H something -u toto get key, you can simply have ENTRYPOINT ["redis", "-H", "something", "-u", "toto"] and then run like this for the same result: docker run redisimg get key.

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

    CMD:

    • CMD ["executable","param1","param2"]: ["executable","param1","param2"] is the first process.
    • CMD command param1 param2: /bin/sh -c CMD command param1 param2 is the first process. CMD command param1 param2 is forked from the first process.
    • CMD ["param1","param2"]: This form is used to provide default arguments for ENTRYPOINT.

    ENTRYPOINT (The following list does not consider the case where CMD and ENTRYPOINT are used together):

    • ENTRYPOINT ["executable", "param1", "param2"]: ["executable", "param1", "param2"] is the first process.
    • ENTRYPOINT command param1 param2: /bin/sh -c command param1 param2 is the first process. command param1 param2 is forked from the first process.

    As creack said, CMD was developed first. Then ENTRYPOINT was developed for more customization. Since they are not designed together, there are some functionality overlaps between CMD and ENTRYPOINT, which often confuse people.

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