RUN vs CMD vs Entrypoint in Docker

The commands RUN, CMD and Entrypoint usually cause a lot of confusion among docker developers. Understanding all the three commands conceptually will help to have a clearer understanding of the same.
When we try to build an image using dockerfile, the instructions are executed step by step. The first instruction is usually pulling a base image such as an OS distribution like ubuntu, centos etc. After that, we modify the base image either by including more images using FROM and AS commands or by modifying the images. Every such instruction creates a new intermediate image build and for each of them, caches are created. The final docker image can be considered as a layered structure where there is a core or a base image and on top of that, there are several layered intermediate images.
To understand all these three commands in depth, we first need to understand what are shell and exec forms.
This form is generally used for Entrypoint and CMD commands. It is of the form -
<instruction> [“executable”, “parameter”, “parameter”, ....]
When we execute an instruction in such a form, shell processing does not happen and the executable is called directly.
Consider the commands below.
RUN [“apt-get”, “install”, “vim”]
ENTRYPOINT [“/bin/echo”, “TutorialsPoint”]
CMD [“/bin/echo”, “TutorialsPoint”]
If we write a dockerfile with the following instructions,
ENV variable TutorialsPoint
ENTRYPOINT [“/bin/echo”, “$variable”]
When we try to run the image, the following output is generated.
$variable
When we try to execute an instruction using the shell form, normal shell processing takes place. It calls the command /bin/sh -c {command} behind the scenes.
It is of the form - <Your instruction> <the command>
Consider the commands below.
RUN apt-get -y update
CMD echo “TutorialsPoint”
ENTRYPOINT echo “TutorialsPoint”
The following dockerfile -
ENV variable TutorialsPoint
ENTRYPOINT echo “$variable”
will output -
TutorialsPoint
Now that we have understood the two forms in-depth, let us continue with the three commands.
The RUN command always gets executed in a new layer. It allows you to install packages and applications on top of an existing image layer and creates a new layer on top of it.
It can be written in both shell and exec forms. Examples include -
RUN apt-get -y update (shell form)
RUN [“apt-get”, “install”, “vim”] (exec form)
Using a CMD command, you will be able to set a default command. This will be executed if you run a particular container without specifying some command. In case you specify a command while running a docker container, the default one will be ignored. Note that if you specify more than one CMD instruction in your dockerfile, only the last one will be executed.
Following are the different ways, through which you can execute a CMD command.
CMD <command> parameter1, parameter2 .... (Shell form)
CMD <command> parameter1, parameter2 .... (Shell form)
CMD [“executable command”, “parameter1”, “parameter2”, ....] (executable form)
CMD [“executable command”, “parameter1”, “parameter2”, ....] (executable form)
CMD [“parameter1”, “parameter2”]
CMD [“parameter1”, “parameter2”]
The third way is used to set some additional default parameters that will be inserted after the default parameters when you are using an ENTRYPOINT in executable form and if you run the container without specifying any arguments in the command line.
Consider the command below inside a dockerfile.
CMD echo “TutorialsPoint”
The output if you run it without specifying arguments (docker run -it image_name) will be -
TutorialsPoint
If you run it by specifying CLI arguments (docker run -it image_name /bin/bash), it will simply open a bash.
It looks similar to a CMD command. However, the difference is that it does not ignore the parameters when you run a container with CLI parameters. The two forms of ENTRYPOINT command are -
ENTRYPOINT <command> parameter1, parameter2, ... (It is shell form)
ENTRYPOINT <command> parameter1, parameter2, ... (It is shell form)
ENTRYPOINT [“executable command”, “parameter1”, “parameter2”, ....] (Executable form)
ENTRYPOINT [“executable command”, “parameter1”, “parameter2”, ....] (Executable form)
When you use an executable 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.
Consider the example below.
ENTRYPOINT [“/bin/echo”, “TutorialsPoint”]
CMD [“Docker”]
If you try to run the container without specifying any CLI arguments (docker run -it image_name), output will be - TutorialsPoint Docker
If you try to run the container without specifying any CLI arguments (docker run -it image_name), output will be - TutorialsPoint Docker
If you specify CLI arguments (docker run -it image_name DockerTutorials), output will be - TutorialsPoint DockerTutorials.
If you specify CLI arguments (docker run -it image_name DockerTutorials), output will be - TutorialsPoint DockerTutorials.
To conclude, if you want to specify default arguments and want it to be overwritten on specifying CLI arguments, use CMD commands. And if you want to run a container with the condition that a particular command is always executed, use ENTRYPOINT. RUN is simply used to build additional image layers over the base image.