CodeX

Everything connected with Tech & Code. Follow to join our 1M+ monthly readers

Follow publication

Docker Quick Tip: CMD & Entrypoint

Thiago Mendes
CodeX
Published in
5 min readSep 2, 2021

--

Photo by frank mckenna on Unsplash

First of all, we need to understand the basics of a container’s lifecycle.

Containers are created with a simple purpose, to perform a task. When this task ends, the container is also moved to the “Exited” state.

Knowing that, let’s start the game.

Before starting, if you don’t have the docker installed in your local environment, you can use Play with Docker if you want to practice what will be said in this post.

As a first step, let’s simply run an Alpine Linux image via the docker run command.

docker run alpine

After that, if you run the docker ps command, to list the active containers, in the running state, you will see that we don’t have any containers running.

docker psCONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Now, if you run the docker ps command with the -a option, you will notice that we have an Alpine Linux container in the “Exited” state.

docker ps -aCONTAINER ID   IMAGE     COMMAND     CREATED         STATUS                     PORTS     NAMES441f5a414b40   alpine    "/bin/sh"   3 seconds ago   Exited (0) 2 seconds ago             naughty_elgamal

Note: The -a option shows all containers regardless of status, while the docker run command without -a only shows running containers.

Now, let’s run the run command again, but differently, with some additional instructions.

docker run alpine echo HelloHello

Note that in this case, the output of the execution was the word “Hello”.

This time, if you run the ps -a docker again, you will notice a small change, the value of the COMMAND column.

docker ps -aCONTAINER ID   IMAGE     COMMAND        CREATED         STATUS                     PORTS     NAMESeffdd406f285   alpine    "echo Hello"   2 minutes ago   Exited (0) 2 minutes ago             keen_euclidb7e953228af4   alpine    "/bin/sh"      2 minutes ago   Exited (0) 2 minutes ago             awesome_chatterjee

To understand what’s happening here, let’s look at two things:

1) The docker run command:

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Note that in addition to the OPTIONS, the RUN command can also receive a COMMAND and ARGS. Knowing this, if we analyze the execution of the command above, with the instructions “echo Hello” and after that, the output of the execution of the command “docker ps -a”, where we notice the change in the value of the COMMAND column, we see that we had a change in the task performed by the container.

Note: In this scenario, “echo” was interpreted as COMMAND and “Hello” as ARGS.

But what happens when I don’t enter COMMAND and (or) ARGS?

To explain this, let’s go-to item 2.

2) Let’s look at the Alpine Image Dockerfile:

FROM scratch
ADD alpine-minirootfs-3.14.2-x86_64.tar.gz /
CMD ["/bin/sh"]

Every image must contain a CMD or Entrypoint, which represents what the container’s task should perform during its lifecycle. In the case of Alpine, we see that the CMD is “/bin/sh”. However, we can override the default CMD during the “docker run” command through COMMAND, as we did in the case of “echo Hello” above.

But where does Entrypoint fit, what is the difference between it and CMD?

To explain this, let’s think about the following scenario, let’s say we’d like to have an image that gets a name and returns the phrase “Hello + the name entered”, but we don’t want to keep passing the command “echo“ every time we run a container to from this image, we just want to insert the name as a parameter.

To exemplify this, let’s create a custom image from Alpine to meet this requirement.

To create our image, the Dockerfile would look like this:

FROM alpineENTRYPOINT ["echo", "Hello"]

With the Dockerfile ready, let’s build our image. In the same directory where the Dockerfile file is located, execute the following command:

docker build -t custom-alpine .

Now to see if our image was created correctly, let’s run the “docker images” command.

docker imagesREPOSITORY      TAG       IMAGE ID       CREATED      SIZEalpine          latest    14119a10abf4   4 days ago   5.6MBcustom-alpine   latest    f92503ca5a3f   4 days ago   5.6MB

Now let’s run a container from our custom image, informing a name as an argument.

docker run custom-alpine ThiagoHello Thiago

As per the requirement of the proposed scenario, the name was included as an item in the Entrypoint array and thus the container printed the phrase “Hello Thiago”.

Thus, we can summarize that the main difference between CMD and Entrypoint, is that in the case of Entrypoint you can keep a default command without it being overwritten during the execution of the “docker run” command, whereas in the case of CMD, the command is overwritten.

Now, what if we wanted to keep a default name in case a name is not provided when executing the “docker run” command?
For that, we can combine the use of Entrypoint with CMD, and our Dockerfile would look like this:

FROM alpineENTRYPOINT ["echo", "Hello"]CMD ["Tony Stark"]

With the Dockerfile changed as above, let’s run a build of our image, now generating version 2 of it.

docker build -t custom-alpine:v2

With the build of the image done, let’s now run a container from this new image without informing any name.

docker run custom-alpine:v2Hello Tony Stark

Note that now, without providing a name, the phrase “Hello Tony Stark” is presented as the output of the task performed by the container.

If we run a new container, now informing a name as a parameter, we have the following output:

docker run custom-alpine:v2 ThiagoHello Thiago

Quick tip

In the case of a container orchestrator like Kubernetes, the CMD parameter is replaced through the “args” attribute and the Entrypoint through the “command” attribute, inside the container spec in YAML.

In the case of the example above, we would have something like:

apiVersion: v1
kind: Pod
metadata:
name: custom-alpine-pod
spec:
containers:
- name: custom-alpine-container
image: custom-alpine:v2
command: ["echo", "Hello"]
args: ["Tony Stark"]

Note: This is just an example of working with CMD and Entrypoint in Kubernetes.

Conclusion

Well, I hope I’ve clarified a little bit the difference between CMD and Entrypoint in the lifecycle of Docker containers, when to use one or the other, and when to combine them.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

CodeX
CodeX

Published in CodeX

Everything connected with Tech & Code. Follow to join our 1M+ monthly readers

Thiago Mendes
Thiago Mendes

No responses yet

Write a response