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>
Examples
RUN apt-get -y update
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"
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”
when container runs as docker run -it <image>
will produce output
Tutorials
Note that variable name is replaced with its value.
Exec form
<instruction> ["executable", "param1", "param2", ...]
Examples
RUN ["apt-get", "install", "python3"]
ENTRYPOINT [“/bin/echo”, “Tutorials”]
CMD [“/bin/echo”, “Tutorials”]
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”]
when container runs as docker run -it will produce output
$variable
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"]
when container runs as docker run -it <image>
will produce output
Tutorials
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
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"
when container runs as docker run -it <image>
will produce output
Hello world
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:/#
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"]
when container runs as docker run -it <image>
will produce output
Tutorials Docker
but when container runs as docker run -it <image> DockerTutorials
will result in
Tutorials DockerTutorials
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 (2)
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"]
Your content is similar to codewithyury.com/docker-run-vs-cmd... A lot, a little bit of modification. You should give some credit to the source.