In this article, we will see the difference between Docker CMD and ENTRYPOINT with the help of examples. According to Docker official documentation, both CMD and ENTRYPOINT instructions define what command gets executed when running a container. But often it becomes very confusing for lot of people to understand the difference and usage of both of these instruction. To understand more about its usage, you need to first understand the rules given in the documentation:-
- Dockerfile should specify at least one of CMD or ENTRYPOINT commands.
- ENTRYPOINT should be defined when using the container as an executable.
- CMD should be used as a way of defining default arguments for an ENTRYPOINT command or for executing an ad-hoc command in a container.
- CMD will be overridden when running the container with alternative arguments.
Docker CMD vs ENTRYPOINT
If you want to always run a specific command inside a docker container then one option you have is to hard code that command using CMD instruction. So that whenever you start the container, it will run that command inside the container. So here basically command argument is fixed and nothing can be overridden. To explain this further, Let's take a simple example of below Dockerfile where we are using the
alpine 3.14 base image and passing bash command
sleep 5 in the CMD instruction. While there are multiple ways to pass bash command in CMD instruction but we will stick to the JSON way of writing.
root@localhost:~# nano Dockerfile FROM alpine:3.14 CMD ["sleep", "5"]
When you build the above dockerfile using docker build -t demo . command then it should build like below.
root@localhost:~# docker build -t demo . Sending build context to Docker daemon 12.23GB Step 1/2 : FROM alpine:3.14 3.14: Pulling from library/alpine 97518928ae5f: Pull complete Digest: sha256:635f0aa53d99017b38d1a0aa5b2082f7812b03e3cdb299103fe77b5c8a07f1d2 Status: Downloaded newer image for alpine:3.14 ---> 0a97eee8041e Step 2/2 : CMD ["sleep", "5"] ---> Running in 8f13e4975685 Removing intermediate container 8f13e4975685 ---> e5edd4d8b443 Successfully built e5edd4d8b443 Successfully tagged demo:latest
Now when you run this container using
docker run demo command then it should run
sleep 5 command inside the container due which you will see below command will make container sleep for 5 secs before getting exited out.
root@localhost:~# docker run demo
The other option that you have is to completely override the command given in CMD by passing different command during the start of the container. This will override any command given in CMD instruction. For example, you can simply run
docker run demo pwd command. It will override the
sleep 5 with
pwd command and gives you the output of
pwd instead of
root@localhost:~# docker run demo pwd /
As you have seen above, CMD is always used when you have to run some fixed command inside a container. But what about a case where you always need to change only the command argument and not the command itself. In that case CMD will no longer be useful. For those cases, you need to use ENTRYPOINT. Using this docker instruction, you can just pass the bash command inside ENTRYPOINT and argument can be passed at the time of starting the container.
root@localhost:~# nano Dockerfile FROM alpine:3.14 ENTRYPOINT ["sleep"]
You can build the above image using same
docker build -t demo . command.
root@localhost:~# docker build -t demo . Sending build context to Docker daemon 12.23GB Step 1/2 : FROM alpine:3.14 ---> 0a97eee8041e Step 2/2 : ENTRYPOINT ["sleep"] ---> Running in 63c4190b0cdf Removing intermediate container 63c4190b0cdf ---> 2b97d9da58b1 Successfully built 2b97d9da58b1 Successfully tagged demo:latest
Once the build is successful, you can run the container using
docker run demo 5 command. It basically means that you are running
sleep 5 command during the start of the container. So when you run this, you will notice that container will sleep for 5 seconds before it get exited out.
root@localhost:~# docker run demo 5
If you now try to run different command or pass any argument which was not expected by sleep command then you will see an error on the output like below. This also confirms that you cannot override the command given in the ENTRYPOINT instruction.
root@localhost:~# docker run demo pwd sleep: invalid number 'pwd'
3. Using both CMD and ENTRYPOINT
You might also encounter a scenario where you need to do both that is, pass only the argument to the command or override the complete command or sometimes may use only the command without any arguments. So for cases like this where you need to configure a default value, it is always recommended to use both ENTRYPOINT and CMD together. ENTRYPOINT will allow arguments to be passed to the command and CMD will allow the command to be completely overridden with new command at the start of the container. So now the Dockerfile will look like this.
root@localhost:~# nano Dockerfile FROM alpine:3.14 ENTRYPOINT ["sleep"] CMD ["10"]
If you now build this Image using
docker build -t demo . command then it should look like below.
root@localhost:~# docker build -t demo . Sending build context to Docker daemon 12.23GB Step 1/3 : FROM alpine:3.14 ---> 0a97eee8041e Step 2/3 : ENTRYPOINT ["sleep"] ---> Using cache ---> 2b97d9da58b1 Step 3/3 : CMD ["10"] ---> Running in 34f1645489cc Removing intermediate container 34f1645489cc ---> 44eacfa0dec2 Successfully built 44eacfa0dec2 Successfully tagged demo:latest
Finally run the container without any command or argument. By default, this should run
sleep 10 command inside the container.
root@localhost:~# docker run demo