CMD and ENTRYPOINT

Objectives

In this lesson, we will learn about two important Dockerfile commands:

  • CMD and ENTRYPOINT.

These commands allow us to set the default command to run in a container.

Defining a default command

When people run our container, we want to greet them with a nice hello message, and using a custom font.

For that, we will execute:

figlet -f script hello
  • -f script tells figlet to use a fancy font.

  • hello is the message that we want it to display.

Adding CMD to our Dockerfile

Our new Dockerfile will look like this:

FROM ubuntu
RUN apt-get update
RUN ["apt-get", "install", "figlet"]
CMD figlet -f script hello
  • CMD defines a default command to run when none is given.

  • It can appear at any point in the file.

  • Each CMD will replace and override the previous one.

  • As a result, while you can have multiple CMD lines, it is useless.

Build and test our image

docker build -t figlet .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM ubuntu
 ---> 452a96d81c30
Step 2/4 : RUN apt-get update
 ---> Using cache
 ---> 01e04143b340
Step 3/4 : RUN ["apt-get", "install", "figlet"]
 ---> Using cache
 ---> ba8d944adee0
Step 4/4 : CMD figlet -f script hello
 ---> Running in 9ab6d5965c4c
Removing intermediate container 9ab6d5965c4c
 ---> d06ea4383cc6
Successfully built d06ea4383cc6
Successfully tagged figlet:latest
# docker run figlet

Overriding CMD

If we want to get a shell into our container (instead of running figlet), we just have to specify a different program to run:

$ docker run -it figlet bash
  • We specified bash.

  • It replaced the value of CMD.

Using ENTRYPOINT

We want to be able to specify a different message on the command line, while retaining figlet and some default parameters.

In other words, we would like to be able to do this:

$ docker run figlet salut

We will use the ENTRYPOINT verb in Dockerfile.

Adding ENTRYPOINT to our Dockerfile

Our new Dockerfile will look like this:

FROM ubuntu
RUN apt-get update
RUN ["apt-get", "install", "figlet"]
ENTRYPOINT ["figlet", "-f", "script"]
  • ENTRYPOINT defines a base command (and its parameters) for the container.

  • The command line arguments are appended to those parameters.

  • Like CMD, ENTRYPOINT can appear anywhere, and replaces the previous value.

Why did we use JSON syntax for our ENTRYPOINT ?

Implications of JSON vs string syntax

  • When CMD or ENTRYPOINT use string syntax, they get wrapped in sh -c.

  • To avoid this wrapping, we can use JSON syntax.

What if we used ENTRYPOINT with string syntax ?

$ docker run figlet salut

This would run the following command in the figlet image:

sh -c “figlet -f script” salut

Build and test our image

Let’s build it:

$ docker build -t figlet .

    Successfully built cede00171081
    Successfully tagged figlet:latest

And run it:

$ docker run figlet salut

Using CMD and ENTRYPOINT together

What if we want to define a default message for our container?

Then we will use ENTRYPOINT and CMD together.

  • ENTRYPOINT will define the base command for our container.

  • CMD will define the default parameter(s) for this command.

They both have to use JSON syntax.

CMD and ENTRYPOINT together

Our new Dockerfile will look like this:

FROM ubuntu
RUN apt-get update
RUN ["apt-get", "install", "figlet"]
ENTRYPOINT ["figlet", "-f", "script"]
CMD ["hello world"]
  • ENTRYPOINT defines a base command (and its parameters) for the container.

  • If we don’t specify extra command-line arguments when starting the container, the value of CMD is appended.

  • Otherwise, our extra command-line arguments are used instead of CMD.

Build and test our image

Let’s build it:

# docker build -t figlet .

Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM ubuntu
 ---> 452a96d81c30
Step 2/5 : RUN apt-get update
 ---> Using cache
 ---> 01e04143b340
Step 3/5 : RUN ["apt-get", "install", "figlet"]
 ---> Using cache
 ---> ba8d944adee0
Step 4/5 : ENTRYPOINT ["figlet", "-f", "script"]
 ---> Using cache
 ---> cede00171081
Step 5/5 : CMD ["hello world"]
 ---> Running in 5019ef053005
Removing intermediate container 5019ef053005
 ---> 848a294a8347
Successfully built 848a294a8347
Successfully tagged figlet:latest

Overriding the image default parameters

Now let’s pass extra arguments to the image.

docker run figlet hola mundo
| |         | |                                      |
| |     __  | |  __,     _  _  _           _  _    __|   __
|/ \   /  \_|/  /  |    / |/ |/ |  |   |  / |/ |  /  |  /  \_
|   |_/\__/ |__/\_/|_/    |  |  |_/ \_/|_/  |  |_/\_/|_/\__/

We overrode CMD but still used ENTRYPOINT.

Overriding ENTRYPOINT

What if we want to run a shell in our container ?

We cannot just do docker run figlet bash because that would just tell figlet to display the word “bash.”

We use the –entrypoint parameter:

$ docker run -it --entrypoint bash figlet