Sunday, July 3, 2022

Docker 101 - Dockerfile - CMD and ENDTRYPOINT

 


Dockerfile Instructions - CMD



The main purpose of a CMD is to provide defaults for an executing container.

Take the following experiment as an example, if we use the base image (ubuntu:22.10) without any future configuration in Dockerfile, when running this container, it should use default CMD from base image if we don't pass any CMD.

Dockerfile:
FROM ubuntu:22.10

Ex:
$ docker image build -t cmd-default-exp .

Result:
Sending build context to Docker daemon  2.048kB
  Step 1/1 : FROM ubuntu:22.10
  22.10: Pulling from library/ubuntu
  415d72858c74: Pull complete
  Digest: sha256:d2d9a7a7b18ecb6a33befb2ca9d38646...
  Status: Downloaded newer image for ubuntu:22.10
  ---> 8264e2ec2ece
  Successfully built 8264e2ec2ece
  Successfully tagged cmd-default-exp:latest

If we run this image without passing CMD, it will execute bash.

Ex:
$ docker container run -it cmd-default-exp

Result:
root@fd967f242443:/#

Why? Because base image (ubuntu:22.10) set 'bash' as default CMD.
And we can use image history command to get more image information.

Ex:
$ docker image history cmd-default-exp

Result:
IMAGE          CREATED      CREATED BY                                  
8264e2ec2ece   5 days ago   /bin/sh -c #(nop)  CMD ["bash"]            
  <missing>      5 days ago   /bin/sh -c #(nop) ADD file:440048...

SIZE       COMMENT
0B
70.2MB

In addition, there can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect.

Take the following as an example, in Dockerfile, we will provide another CMD (to replace default CMD from base image).

Dockerfile:
FROM ubuntu:22.10
  CMD ["echo", "Hello World"]

Ex:
$ docker image build -t cmd-override-exp .

Result:
Sending build context to Docker daemon  2.048kB
  Step 1/2 : FROM ubuntu:22.10
  ---> 8264e2ec2ece
  Step 2/2 : CMD ["echo", "Hello World"]
  ---> Running in 35c49b6ad01c
  Removing intermediate container 35c49b6ad01c
  ---> cd72d2059deb
  Successfully built cd72d2059deb
  Successfully tagged cmd-override-exp:latest

Ex:
$ docker container run -it cmd-override-exp

Result:
Hello World

If the user specifies arguments to docker run then they will override the default specified in CMD.

Ex:
$ docker container run -it cmd-override-exp echo 'Hi there'

Result:
Hi there


Dockerfile Instructions - ENTRYPOINT



An ENTRYPOINT allows you to configure a container that will run as an executable.

It may confuse you with CMD instruction. The difference is that CMD is to set the defaults for an executable contianer, and it will be overridden once we pass parameters when we run container.
On the other hand, ENTRYPOINT will not be overridden if we pass parameters, and it will take those parameters as its parameters instead.

Let's start with the basic usage for ENTRYPOINT.

Dockerfile:
FROM ubuntu:22.10 ENTRYPOINT ["echo", "Hello World by ENTRYPOINT"]

Ex:
$ docker image build -t basic-entrypoint .

Result:
Sending build context to Docker daemon  2.048kB
  Step 1/2 : FROM ubuntu:22.10
  ---> 8264e2ec2ece
  Step 2/2 : ENTRYPOINT ["echo", "Hello World by ENTRYPOINT"]
  ---> Running in 928ec8c1c0cb
  Removing intermediate container 928ec8c1c0cb
  ---> deb8931985d6
  Successfully built deb8931985d6
  Successfully tagged basic-entrypoint:latest

Ex:
$ docker container run basic-entrypoint

Result:
Hello World by ENTRYPOINT

Normally, ENTRYPOINT will work with CMD (as default parameters to ENTRYPOINT).

Dockerfile:
FROM ubuntu:22.10
ENTRYPOINT ["echo", "Hello World by ENTRYPOINT"]
  CMD ["and CMD"]


Ex:
$ docker image build -t entrypoint-and-cmd .

Result:
Sending build context to Docker daemon  2.048kB
  Step 1/3 : FROM ubuntu:22.10
  ---> 8264e2ec2ece
  Step 2/3 : ENTRYPOINT ["echo", "Hello World by ENTRYPOINT"]
  ---> Using cache
  ---> deb8931985d6
  Step 3/3 : CMD ["and CMD"]
  ---> Running in c7aa29573689
  Removing intermediate container c7aa29573689
  ---> 3dd20846ece3
  Successfully built 3dd20846ece3
  Successfully tagged entrypoint-and-cmd:latest

Ex:
$ docker container run entrypoint-and-cmd

Result:
Hello World by ENTRYPOINT and CMD

So if we do not pass parameters when running container, then ENDTRYPOINT and CMD will work together. In this case, CMD will be treated as ENDTRYPOINT parameter.

Ex:
$ docker container run entrypoint-and-cmd and Parameters

Result:
Hello World by ENTRYPOINT and Parameters

On the other hand, if we pass parameters when running container, then the default value of CMD will be ignored, and the passed parameters will be treated as ENDTRYPOINT parameters.

No comments:

Post a Comment