The difference between ENTRYPOINT and CMD in Dockerfile

The difference between ENTRYPOINT and CMD in Dockerfile

In the Docker system learning tutorial, we learned that using Dockerfile to build a Docker image is a standard way. According to the Dockerfile, we can understand the details of the components installed in the image.

Dockerfile generally consists of four parts: first, the base image to be built; second, the information of the image builder; third, instructions for adding image layers during the image building process; and fourth, the program executed when the container is started by the image.

The ENTRYPOINT and CMD involved in this article belong to the last part of the Dockerfile. These two Dockerfile instructions are used to tell the Docker background program to execute when starting the image. There are subtle differences between the two.

The following will explain the two instructions in detail from the perspective of their similarities and differences as well as advanced techniques for using the two together.

CMD command

The CMD instruction specifies the program to be run when the container is started. Generally, the simplest way to start a container is to use docker run to pass parameters to the docker command.

docker run -it image /bin/bash

The /bin/bash at the end actually passes parameters to tell the container to run a shell when it starts. This process can be replaced by the CMD command equivalently

CMD ['/bin/bash']

Therefore, when the command specified by the CMD instruction exists in the Dockerfile, the container can be started without passing parameters.

docker run -it image

The execution effect is consistent.

[root@MiWiFi-R3L-srv test]# docker run --name test -it test_image

[root@3a1bb0c9e35c /]#

If the Dockerfile has specified a program to run when the container is started, and command line parameters are used when starting the container with docker run, the cmd instruction in the Dockerfile will be invalid.

docker run -it image /bin/ps

It is found that there is no shell after starting the container, only the process status in the current container is printed, and the cmd instruction effect is overwritten.

 PID TTY TIME CMD
  1 ? 00:00:00 ps
[root@MiWiFi-R3L-srv test]#

At this point you can see that the cmd effect is covered. In a Dockerfile, only the last cmd instruction is valid, so only one cmd instruction should be written in a Dockerfile.

ENTRYPOINT instruction

The effect of the ENTRYPOINT instruction is very similar to that of CMD, and it is easy to confuse the functions of the two. The biggest difference lies in the way of use. The command specified by ENTRYPOINT needs to be used with the docker run command to start the container. The content following the docker run instruction is used as a parameter as the parameter of the running command specified by the ENTRYPOINT instruction. The linux command specified by ENTRYPOINT is generally not overwritten.

Take nginx image as an example

First, build an nginx image and specify nginx as the program to be executed when the container is running.

FROM centos
MAINTAINER allocator
RUN yum install -y nginx
RUN echo 'hello world' > /usr/share/nginx/html/index.html
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx"]

Then start the mirror

docker run --name test -p 5000:80 -it test_nginx -g "daemon off"

The last two are passed as parameters to the nginx startup program to run. At this time, nginx runs as a foreground program and is a web server. You can see hello world normally through the browser according to the externally bound port.

Tips for using both together

Now that you understand the difference between the two, you can use their characteristics to build an image that contains a default startup program and supports manually specifying the parameters for the startup program when starting docker run.

For example. Use ENTRYPOINT to specify the startup of the nginx program, and give the default running parameters to display help information. The dockerfile is constructed as follows:

ENTRYPOINT ["/usr/sbin/nginx"]

CMD ["-h"]

When you use docker run --name test -it test_nginx without passing any parameters, the command after the cmd instruction is used as the default parameter when starting the container, and the help information of nginx is printed. At this time, the content after cmd is not a complete command, but a parameter. If its content is a complete command, it will overwrite the content in ENTRYPOINT.

If you use docker run --name test -it test_nginx -g "daemon off" to start, the given running parameters will overwrite the content corresponding to the CMD instruction. At this time, nginx will run as a foreground process and be used as a web server. You can see hello world through the browser

Additional knowledge: Tips for writing docker-entrypoint.sh entry files

In the official Docker registry (store.docker.com), popular third-party applications provide links to Dockerfiles on their pages. Many Dockerfiles have ENTRYPOINT commands written like this ["docker-entrypoint.sh"]

This article will introduce the special usage and design logic of docker-entrypoint.sh

MySQL

set -e

Every script you write should start with set -e, which tells bash to exit if any statement evaluates to anything other than true. This helps prevent errors from snowballing into a fatal error that should have been handled earlier. For increased readability, use set -o errexit, which does the same thing as set -e.

set -o pipefail

The design purpose is the same as above, that is, you want to exit immediately after the execution error, and do not execute further. The scope of -o pipefail is the pipeline, that is, in the Linux script, if the previous command fails to execute, it should exit immediately.

shopt -s nullglob

When using wildcards in Linux, such as * ?, if no file is matched, it will not report "No such file or directory" but will remove the parameters after the command and execute it.

if [ “${1:0:1}” = '-' ]; then…

This is a judgment statement. In the official document, the previous line has been commented out: if command starts with an option, prepend mysqld

The judgment statement is ${1:0:1}, which means judging $1 (the first parameter of calling the script), offset 0 (no offset), and taking a character (taking the length of the string)

If the first character of the parameter following the script is a hyphen, then all subsequent strings are considered to be mysqld startup parameters.

The above operation is similar to Python's string slicing

set –mysqld “$@”

After determining that the first parameter starts with -, the set -- mysqld "$@" command is executed. The set -- syntax is used. set -- will store all the strings separated by spaces in the $1, $2, and $3 variables in order, where the new $@ is the entire content after set --

For example: bash docker-entrypoint.sh -f xxx.conf

In this case, the value of $@ in set --mysqld "$@" is -f xxx.conf

After executing the command set --mysqld "$@":

$1=mysqld
$2=-f
$3=xxx.conf
$@=mysqld -f xxx.conf

You can see that when the docker-entrypoint.sh script is executed with the -x parameter added, the value of $@ changes. On the basis of the original $@ value, the mysqld command is pre-added in front.

exec “$@”

In almost every last line of the docker-entrypoint.sh script, the exec "$@" command is executed.

The significance of this command is that you have anticipated the call scenarios that should be expected for your image. When the person who actually uses the image executes an executable command that you did not expect, it will go to the last line of the script to execute the user's new executable command.

Situation Assessment

The last line of the script is directly mentioned above. In the previous script, you need to fully consider the situations in which your own script may be called. Let's take the official MySQL dockerfile as an example. It determines the following situations:

Starting with -, it is considered as a parameter

The name starts with mysqld and the user ID is 0 (root user)

The case where mysqld is at the beginning

After determining all the calling forms of your application, you should add the exec "$@" command at the end

${mysql[@]}

Arrays in the Shell, directly executing ${mysql[@]} will execute this array as an executable program

➜ /tmp mysql=(mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )
➜ /tmp echo ${mysql[1]}
mysql
➜ /tmp echo ${mysql[2]}
--protocol=socket
➜ /tmp echo ${mysql[3]}
-uroot
➜ /tmp echo ${mysql[4]}
-hlocalhost
➜ /tmp echo ${mysql[@]}
mysql --protocol=socket -uroot -hlocalhost --socket=
exec gosu mysql “$BASH_SOURCE” “$@”

The gosu command here is a lightweight "replacement" for the sudo command in Linux

gosu is a tool developed in golang language, which is used to replace the sudo command in shell. The su and sudo commands have some defects, mainly causing uncertain TTY and problems with signal forwarding. If you just want to run a program with a specific user, using su or sudo is too heavy, so gosu came into being.

gosu directly borrows the principle of libcontainer to start applications in containers and uses /etc/passwd to process applications. gosu first finds the specified user or user group, and then switches to that user or user group. Next, it uses exec to start the application. So far, gosu has completed its work and will not participate in the subsequent declaration cycle of the application. This method avoids the problem of gosu handling TTY and forwarding semaphores, and directly hands these two tasks to the application to complete

The above description of the difference between ENTRYPOINT and CMD in Dockerfile is all the content that the editor shares with you. I hope it can give you a reference. I also hope that you will support 123WORDPRESS.COM.

You may also be interested in:
  • Use non-root users to execute script operations in docker containers
  • Docker file storage path, get container startup command operation
  • Solution to the problem that docker CMD/ENTRYPOINT executes the sh script: not found/run.sh:

<<:  Universal solution for MySQL failure to start under Windows system

>>:  Tips for making web table frames

Recommend

Exploration of three underlying mechanisms of React global state management

Table of contents Preface props context state Sum...

How to simulate enumeration with JS

Preface In current JavaScript, there is no concep...

How to install common components (mysql, redis) in Docker

Docker installs mysql docker search mysql Search ...

52 SQL statements to teach you performance optimization

1. To optimize the query, try to avoid full table...

Detailed explanation of the difference between chown and chmod commands in Linux

In Linux system, both chmod and chown commands ca...

Methods and techniques for designing an interesting website (picture)

Have you ever encountered a situation where we hav...

A brief discussion on the maximum number of open files for MySQL system users

What you learn from books is always shallow, and ...

Experience in designing a layered interface in web design

Many netizens often ask why their websites always ...

Detailed explanation of the use cases of Vue listeners

The first one is to use jQuery's ajax to send...

Detailed explanation of type protection in TypeScript

Table of contents Overview Type Assertions in syn...

Two ways to build a private GitLab using Docker

The first method: docker installation 1. Pull the...

Specific implementation methods of MySQL table sharding and partitioning

Vertical table Vertical table splitting means spl...

Analysis of several reasons why Iframe should be used less

The following graph shows how time-consuming it is...