We IT people LOVE tinkering with new tech stuff, and Docker is no exception. As a matter of fact, Docker was ranked as the #1 most wanted platform, #2 most loved platform, and #3 most broadly used platform in the 2019 Stack Overflow Developer Survey, and #1 most wanted platform, #2 most loved platform and #3 most popular platform in the 2020 edition of the same survey.
If you've bumped into this article, chances are that you have been bamboozled by the fruit doggo difference between the CMD
and ENTRYPOINT
instructions defined in a Dockerfile, used to describe how a Docker container should be run.
But what's a Docker container?
Containers are lightweight, standalone, executable packages of software designed for running specific tasks, no matter if short-lived or long-running. Therefore, a container's lifecycle depends on the ongoing process inside of it.
Once the process stops, the container stops as well.
Ok, but what role is our Dockerfile playing here?
Containers are dependent on images and use them to construct a run-time environment in order to run an application. A Dockerfile is a script which role is to define the process which leads to the creation of a final image, and how to run a container bound to said image.
The process of creating a Docker image usually begins with a FROM
command, defining a base image to build our image upon. We usually follow up with a bunch of RUN
instructions, used to run commands which modify the underlying filesystem.
Each
RUN
instruction creates a new image layer that contains a modification to the filesystem.
Fine. Now what about the CMD vs ENTRYPOINT stuff?
CMD
and ENTRYPOINT
are two different types of instructions used to define how a Docker container should be run.
Let's dive into the details of each one:
CMD
A CMD
instruction defines the default command used to run a Docker container from an image.
Given a simple image like the following:
FROM alpine
CMD ["echo", "Hello, World!"]
Running it with:
docker container run my-container
Will yield the following result:
Hello, World!
A Dockerfile can contain multiple
CMD
instructions, but every single one of them, except for the last one, will be ignored.
A CMD
instruction can be overridden by the arguments passed to docker container run
, like:
docker container run my-container echo "Hello again!"
Will yield:
Hello again!
ENTRYPOINT
ENTRYPOINT
instructions define, just like their CMD siblings, the default command used to start a container.
FROM alpine
ENTRYPOINT ["echo", "Hello, World!"]
Will yield:
Hello, World!
Cool, so... what's the difference at this point?
Well, the main difference is that, if both a CMD
and ENTRYPOINT
instructions are defined inside a Dockerfile, the CMD
instruction will be concatenated to the ENTRYPOINT
one:
FROM alpine
ENTRYPOINT ["echo"]
CMD ["Hello, World!"]
Wil lead to us seeing:
Hello, World!
Also, while CMD
instructions are, by design, made do be easily overridden by passing arguments to docker container run
commands, ENTRYPOINT
have purposely been made harder to override manually, by forcing user to use a --entrypoint
flag.
This leads us to a pattern
This design leads us to a consistent pattern. And we like patterns, patterns are good for our mental health:
We can use ENTRYPOINT
to define a base command which always gets executed, and CMD
to define default arguments for this command, easily overridable by passing custom args to docker container run
.
Top comments (3)
Entrypoint is the main program to execute. E.g. /bin/bash
Comand is used to pass parameters.
The good thing about comand is, that you can provide a default fallback for the compose file and OVERWRITE it if needed when using the docker CLI.
I've always like kubernetes choice to call it command and args. Always made more sense to me than entrypoint and cmd for arguments.
ENTRYPOINT is the first process 1 of the instance (PID 0). Some systems currently use TINI to manage zombie processes and other stuff.