Docker provides a couple of instructions to specify what a container does when you want to docker run it: CMD and ENTRYPOINT.

These two provide a somewhat similar functionality but are actually quite different fundamentally. According to the Dockerfile reference, CMD’s entire purpose is to provide defaults for an executing container, while ENTRYPOINT’s is being concerned with the configuration of said executing container.

That’s their main purpose. However, depending on the combination of this two instructions, we can achieve different use cases.

CMD

Let’s take a look at Debian Stretch Slim’s Dockerfile:

FROM scratch
ADD rootfs.tar.xz /
CMD ["bash"]

Notice how there’s no ENTRYPOINT. When only CMD is present, the default behaviour will be to execute whatever is specified by CMD, bash in this case.

So, when I docker run debian:stretch-slim, the container will run bash and exit.

Wouldn’t ENTRYPOINT achieve the same thing? Why do we need CMD for then? Well, CMD has a special property, something I like to call soft exec, which is basically the ability to override the command. Take a look:

$ docker run debian:stretch-slim echo Hello!
Hello!

The container executed echo Hello! instead of the default command.

ENTRYPOINT

Let’s contrast the previous behaviour with an ENTRYPOINT instruction. Using the following Dockerfile:

FROM debian:stretch-slim
ENTRYPOINT ["echo" "Hello,"]

I’m gonna build a entrypoint-test image and run it:

$ docker run entrypoint-test
Hello,

Okay, so far things look samey. But watch this!

$ docker run entrypoint-test World!
Hello, World!

I couldn’t override the command this time! Instead, the container used it as echo’s input. This is what I call the hard exec: ENTRYPOINT will always be executed, regardless.

ENTRYPOINT + CMD

As I mentioned, CMD provides default arguments to ENTRYPOINT. Consider the following Dockerfile:

FROM debian:stretch-slim
CMD ["World!"]
ENTRYPOINT ["echo", "Hello,"]

Having built it as entrypoint-cmd-test, let’s run it:

$ docker run entrypoint-cmd-test
Hello, World!

CMD provided the default World! argument to echo. What if we pass an argument of our own?

$ docker run entrypoint-cmd-test Daniel!
Hello, Daniel!

We have successfully overridden the default parameters!

Conclusion

Both CMD & ENTRYPOINT bring their own stuff to the table, but at the end of the day, like most things, it’s up to you to decide which use case fits your needs! I hope this has helped clear up the confusion!