ENTRYPOINT
and CMD
are two docker commands that sound interchangeable, but there are important differences that I’ll cover in this post. I suspect CMD
is probably the more familiar instruction, so I’ll go over what that does and how it differs from ENTRYPOINT
.
Here’s the purpose of CMD
, taken straight from the docker manual:
The main purpose of a聽CMD
聽is to provide defaults for an executing container.
https://docs.docker.com/engine/reference/builder/#cmd
If you start a container via docker run
or docker start
and you don’t supply any commands, the last CMD instruction is what gets executed. In most docker files, this effectively acts as “main” or … “entrypoint”. I put entrypoint in quotes both to distinguish it from the formal ENTRYPOINT
instruction and to show you why this naming is confusing!
Here’s an example of a dockerfile that runs the rails server using CMD
FROM ruby:3.2
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
CMD ["rails", "server", "-b", "0.0.0.0"]
Code language: PHP (php)
CMD does not create a new image layer, unlike commands like RUN. It does not do anything at build time. So when you run docker build
to create a docker image from a dockerfile, rails server
is not being executed. It purely a runtime (container runtime) construct. This interleaving of instructions in docker that are intended for difference stages of a container lifecycle is also a common source of confusion for beginner users of docker.
In practice, at least from my experience, CMD
is sufficient. I work on mostly web services and the vast majority of containers are running a server process of some kind using CMD <start server>
after the application dependencies are build. For most situations, this is enough and you never have to think about or even be aware of the existence of ENTRYPOINT
.
Have a nice day.
Just kidding, okay lets go over ENTRYPOINT
now.
Here’s a rather confusing description on dockers website on what ENTRYPOINT
is:
An聽ENTRYPOINT
聽allows you to configure a container that will run as an executable.
https://docs.docker.com/engine/reference/builder/#entrypoint
So CMD
is to provide defaults for an executing container and ENTRYPOINT
is to configure a container that will run as an executable. That’s a little confusing because using CMD
sort of also allows you to run a container as an executable right? You start the container and something executes!
Here’s a simpler definition:
An ENTRYPOINT
is always run. It doesn’t matter what arguments you’re passing when running docker run
. ENTRYPOINT
is never overwritten. If arguments are passed, those are appended to the end of what’s already specified in ENTRYPOINT
.
Here’s an example of using the ENTRYPOINT instruction in a Dockerfile:
FROM ubuntu:latest
ENTRYPOINT ["echo", "Hello, World!"]
Code language: CSS (css)
In this example, the ENTRYPOINT is set to the command echo "Hello, World!"
. When a container is created from this image and started, the message “Hello, World!” will be printed to the console. Running docker run my-image "Welcome"
would result in the message “Hello, World! Welcome” being printed.
Let’s take a look at an example using CMD
to demonstrate the override behavior:
FROM ubuntu:latest
CMD ["echo", "Hello, World!"]
Code language: CSS (css)
In this case, the CMD instruction specifies the default command as echo "Hello, World!"
. However, if a user runs the container with a different command, the specified command will override the CMD instruction. For instance, running docker run my-image "Welcome"
would output “Welcome” instead of the default message “Hello, World!”. The entire command is overridden.
Both CMD
and ENTRYPOINT
can be used together in situations where you want
- A particular command to always execute (this is where
ENTRYPOINT
comes in handy) that cannot be overridden
- A set of default arguments for the
ENTRYPOINT
command
This offers some flexibility in how users of your image can provide custom arguments to alter the runtime behavior of your container. In cases where you don’t need that customization or where it’s perfectly fine for users to provide their own “entrypoints”, just use CMD
.