DEV Community

Kittipat.po
Kittipat.po

Posted on • Updated on

Docker RUN vs CMD vs ENTRYPOINT: Demystifying the Differences

Introduction 💡

Docker, with its powerful containerization capabilities, offers developers a versatile environment to package, distribute, and run applications seamlessly. However, the similarity in syntax between certain Docker instructions can often lead to confusion, especially for newcomers to the technology. In this article, we will delve into the distinctions between the RUN, CMD, and ENTRYPOINT instructions, with clear examples to help you navigate this Docker trio.

A Quick Overview

  • RUN: Executes commands in a new layer, creating a new image. Commonly used for installing software packages.
  • CMD: Sets a default command or parameters that can be overridden when launching a Docker container.
  • ENTRYPOINT: Configures a container to run as an executable.

Let's break down each of these instructions to better understand their roles and implications.

Shell Form vs. Exec Form

Before exploring the instructions, it's crucial to differentiate between two forms of syntax: shell form and exec form. The choice of form significantly influences how instructions are executed.

Shell form

<instruction> <command>
Enter fullscreen mode Exit fullscreen mode

Examples

RUN apt-get -y update
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"
Enter fullscreen mode Exit fullscreen mode

When instruction is executed in shell form it calls /bin/sh -c under the hood and normal shell processing happens. For example, the following snippet in Dockerfile

ENV variable Tutorials
ENTRYPOINT echo “$variable”
Enter fullscreen mode Exit fullscreen mode

when container runs as docker run -it <image> will produce output

Tutorials
Enter fullscreen mode Exit fullscreen mode

Note that variable name is replaced with its value.

Exec form

<instruction> ["executable", "param1", "param2", ...]
Enter fullscreen mode Exit fullscreen mode

Examples

RUN ["apt-get", "install", "python3"]
ENTRYPOINT [“/bin/echo”, “Tutorials”]
CMD [“/bin/echo”, “Tutorials”]
Enter fullscreen mode Exit fullscreen mode

When instruction is executed in exec form it calls executable directly, and shell processing does not happen. For example, the following snippet in Dockerfile

ENV variable Tutorials
ENTRYPOINT [“/bin/echo”, “$variable”]
Enter fullscreen mode Exit fullscreen mode

when container runs as docker run -it will produce output

$variable
Enter fullscreen mode Exit fullscreen mode

Note that variable name is not substituted.

How to run bash?

If you need to run bash (or any other interpreter but sh), use exec form with /bin/bash as executable. In this case, normal shell processing will take place. For example, the following snippet in Dockerfile

ENV variable Tutorials
ENTRYPOINT ["/bin/bash", "-c", "echo $variable"]
Enter fullscreen mode Exit fullscreen mode

when container runs as docker run -it <image> will produce output

Tutorials
Enter fullscreen mode Exit fullscreen mode

RUN

The RUN instruction is commonly used for installing software packages or performing actions during image creation. It executes commands, adds a new layer, and commits the results. Multiple RUN instructions are often used in a Dockerfile.

RUN has two forms:

  • RUN <command> (shell form)
  • RUN ["executable", "param1", "param2"] (exec form)

(The forms are described in detail in Shell and Exec forms section above.)

Examples

RUN apt-get update && apt-get install -y \
  vim \
  tzdata \
  git \
  mercurial \
  subversion
Enter fullscreen mode Exit fullscreen mode

CMD

The CMD instruction specifies a default command to run when the container starts. It can be overridden by providing a command during container launch. If there are multiple CMD instructions, only the last one is effective.

CMD has three forms:

  • CMD ["executable","param1","param2"] (exec form, preferred)
  • CMD ["param1","param2"] (sets additional default parameters for ENTRYPOINT in exec form)
  • CMD command param1 param2 (shell form)

The second one is used together with ENTRYPOINT instruction in exec form. It sets default parameters that will be added after ENTRYPOINT parameters if container runs without command line arguments. See ENTRYPOINT for example.

Let’s have a look how CMD instruction works. The following snippet in Dockerfile

CMD echo "Hello world" 
Enter fullscreen mode Exit fullscreen mode

when container runs as docker run -it <image> will produce output

Hello world
Enter fullscreen mode Exit fullscreen mode

but when container runs with a command, e.g., docker run -it <image> /bin/bash, CMD is ignored and bash interpreter runs instead:

root@7de4bed89922:/#
Enter fullscreen mode Exit fullscreen mode

ENTRYPOINT

The ENTRYPOINT instruction configures a container to run as an executable. It is similar to CMD, but the difference lies in how they handle command line parameters. ENTRYPOINT arguments are always used, while CMD arguments can be replaced by command line arguments when launching the container.

ENTRYPOINT has two forms:

  • ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)
  • ENTRYPOINT command param1 param2 (shell form)

When you use an exec form of ENTRYPOINT command, it will allow you to set additional parameters using CMD command. If you use it in shell form, it will ignore CMD parameters or any CLI arguments.

Examples

ENTRYPOINT ["/bin/echo", "Tutorials"]
CMD ["Docker"]
Enter fullscreen mode Exit fullscreen mode

when container runs as docker run -it <image> will produce output

Tutorials Docker
Enter fullscreen mode Exit fullscreen mode

but when container runs as docker run -it <image> DockerTutorials will result in

Tutorials DockerTutorials
Enter fullscreen mode Exit fullscreen mode

Conclusion 🥂

In summary, Docker's CMD offers flexible default commands that can be overridden, while ENTRYPOINT guarantees a fixed command execution. RUN builds image layers atop the base. These commands play pivotal roles in containerization. CMD prioritizes adaptability, ENTRYPOINT enforces steadfastness, and RUN constructs the image foundation. Understanding their nuances is crucial for effective Dockerfile composition and streamlined container management.

Top comments (1)

Collapse
 
anshulongithub profile image
anshulongithub • Edited

Nice article! just a slight correction, in the How to run bash? section above, we still need to pass the "echo" command there like so:

ENTRYPOINT ["/bin/bash", "-c", "echo $variable"]