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

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


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 bashthe 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.


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:wheezyENTRYPOINT ["/bin/ping"]CMD ["localhost"]

Running the image without any argument will ping the localhost:

$ docker run -it testPING localhost (127.0.0.1): 48 data bytes56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.096 ms56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.088 ms56 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 lossround-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.comPING google.com (173.194.45.70): 48 data bytes56 bytes from 173.194.45.70: icmp_seq=0 ttl=55 time=32.583 ms56 bytes from 173.194.45.70: icmp_seq=2 ttl=55 time=30.327 ms56 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 lossround-trip min/avg/max/stddev = 30.327/36.430/46.379/7.095 ms

For comparison, if your Dockerfile is:

FROM debian:wheezyCMD ["/bin/ping", "localhost"]

Running the image without any argument will ping the localhost:

$ docker run -it testPING localhost (127.0.0.1): 48 data bytes56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.076 ms56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.087 ms56 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 lossround-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 bashroot@e8bb7249b843:/#

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


According to docker docs,

Both CMD and ENTRYPOINT instructions define what command gets executedwhen running a container. There are few rules that describe theirco-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 acontainer.
  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  ║╚════════════════════════════╩═════════════════════════════════════════════════╝