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 -
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':
• 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)
Difference between CMD and ENTRYPOINT by intuition:
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
.
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
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
.
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.