Introduction of Docker ENTRYPOINT
Docker entrypoint is a Dockerfile directive or instruction that is used to specify the executable which should run when a container is started from a Docker image. It has two forms, the first one is the ‘exec’ form and the second one is the ‘shell’ form. If there is no entrypoint or CMD specified in the Docker image, it starts and exits at the same time that means container stops automatically so, we must have to specify entrypoint or CMD so that when we will start the container it should execute something rather than going to stop.
Syntax:
As discussed Docker entrypoint has two forms so we have two different syntaxes as below: –
The ‘exec’ form syntax:
ENTRYPOINT [“executable”, “param1”, “param2”, ..]
Where executable which is going to start when we run the container and “param1” and “param2” are the parameters that we have to pass to that executable.
The ‘shell’ form syntax:
ENTRYPOINT command param1 param2
Where command is the shell command or any executable that we want to run when we start the container and param1 and param2 are the parameters.
How ENTRYPOINT Works in Docker?
As we know, Docker ENTRYPOINT allows us to make a container runnable, however, we can still specify the command while starting the container. Both forms of Docker entrypoint behave differently when we specify any command at run time.
- The ‘exec’ form allows us to specify the command line arguments to the ‘docker run’ command and is appended to the end of all elements of the ‘exec’ form, meaning the specified command will run after the executable specified in entrypoint. For example, if we pass the ‘-d’ argument to the ‘docker run’ command, then Docker daemon will pass that argument to the entrypoint and the specified executable will run in the background.
- The ‘shell’ form does not allow to specify any command or the ‘docker run’ command-line arguments while starting the container as the ENTRYPOINT command runs as a subcommand of ‘/bin/sh -c’. The executable has a different PID than the container’s ‘PID 1’ so if we pass any Unix signals like SIGTERM from the ‘docker stop’ command, the executable does not receive it.
We can override the ENTRYPOINT instruction while starting the container using the ‘–entrypoint’ flag. Also if we have multiple ENTRYPOINT instructions mentioned in Dockerfile then the last ENTRYPOINT will have an effect.
Examples of Docker ENTRYPOINT
Let’s understand the working on Docker entrypoint by some examples.
Example #1 – ‘exec’ form ENTRYPOINT
We want to create an nginx Docker image using Ubuntu as a base image and also want to start the nginx when we run the container automatically.
- We have to create a Dockerfile first with the ‘exec’ form ENTRYPOINT as below: –
FROM ubuntu
RUN apt-get update && apt-get install -y nginx
ENTRYPOINT ["nginx", "-g", "daemon off;"]
- Build the Docker image using the above Dockerfile as shown below: –
docker build -t my-app.
- Run a container using this new Docker image and connect to the newly created container using the ‘docker exec’ command as shown below: –
docker run -d --name my-web my-app
docker exec -it my-web sh
- Now, if we run the ‘top’ command inside the container we can see that the ‘nginx’ is already running with ‘PID 1’.
Example #2 – ‘shell’ form ENTRYPOINT
We are going to use the same scenario as above, however, we will replace the ENTRYPOINT from from ‘exec’ to ‘shell’ in the Dockerfile as below:
- Let’s build the Docker image using build command as below:
docker build -t my-app:v2 .
- Now, run a container using the above Docker image and connect to the newly created container and check the PID of the nginx executable: –
docker run -d --name my-web2 my-app:v2
docker exec -it my-web2 sh
Explanation: In the above snapshot, we can see that the ‘sh’ command is running under ‘PID 1’. It is because nginx is now running as a subcommand of the ‘/bin/sh -c’ command.
- In this way, we cannot stop a long-running ENTRYPOINT executable correctly using the ‘docker stop’ command. If we want to stop the executable correctly we must use the ‘exec’ before the executable in the Dockerfile as shown below:
FROM ubuntu
RUN apt-get update && apt-get install -y nginx
ENTRYPOINT exec nginx -g “daemon off;”
- To verify, it is working as expected, create a new Docker image name ‘my-app:v3’ and run a container using it and once the container is started, connect to it and check PID of the nginx executable again:
docker run -d --name my-web3 my-app:v3
docker exec -it my-web3 sh
Explanation: In the above snapshot, we can see that the nginx executable has PID 1 now.
Example #3
We want to see the entrypoint of a running container. We can do so by using the ‘inspect’ command or ‘docker ps’ command with the ‘format’ flag to get a cleaner output as below: –
docker inspect my-web2
docker ps --format "table {{.ID}} \t {{.Names}} \t {{.Command}}" --no-trunc
Example #4
We want to override the entrypoint while starting the container. We have the ‘–entrypoint’ flag for that. We can use the ‘–entrypoint’ flag to pass the command as below: –
docker run -d --entrypoint sh --name my-web4 my-app
docker run -d --entrypoint sh --name my-web5 my-app:v2
docker run -d --entrypoint sh --name my-web6 my-app:v3
docker ps -a --format "table {{.ID}} \t {{.Names}} \t {{.Command}}" --no-trunc
Explanation: In the above snapshot, we can see that the container ‘my-web4’, ‘my-web5’, and ‘my-web6’ is showing command ‘sh’ because entrypoint has been overridden.
Advantages:
- It allows us to create container executable.
- It provides flexibility to specify additional command-line arguments if we want.
Conclusion
Now, we know that there are two forms of Docker Entrypoint, however, the ‘exec’ form is preferable. We have Docker CMD that also allows us to make container runnable but we get some advantages in Docker ENTRYPOINT over the CMD. Most of the Docker base image has a shell such as /bin/sh or /bin/bash as the CMD executable, for example, ubuntu, busybox, debian, etc.
Recommended Articles
This is a guide to Docker ENTRYPOINT. Here we also discuss the introduction and how entrypoint works in docker? along with different examples and its code implementation. You may also have a look at the following articles to learn more –