CMD vs ENTRYPOINT Docker

Anurag Jain
3 min readNov 8, 2022

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.

Eg. 1

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.

Eg. 2

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

Eg. 3

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:/#

Eg. 4

Lets say Dockerfile is

FROM alpine:3.7ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] 
CMD ["/usr/sbin/crond", "-f", "-L", "/dev/stdout"]

entrypoint.sh

#!/bin/sh 
echo "Hello"
exec tini $@

This will echo Hello and run the following command

tini /usr/sbin/crond -f -L /dev/stdout

Incase you are more curious about What is tini?, tune up !

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 ╚════════════════════════════╩═════════════════════════════════════╝

Reference

--

--