Using exec mode and shell mode, the difference between executing ENTRYPOINT and CMD

Dockerfile is a text document containing instructions for combining images, and Docker automatically generates images by reading the instructions in Dockerfile. Dockerfile is a text document containing instructions for combining images, and Docker automatically generates images by reading the instructions in Dockerfile.

#Part 1 first introduces the three most commonly used instructions in Dockerfile:

RUN

Executes commands and creates new mirror layers, RUN often used to install packages.

For example, install curl in the Docker image of Alpine Linux

FROM alpine:latest
RUN apk add --update curl && rm -rf /var/cache/apk/*

CMD

Set the command and its parameters that are executed by default after the container starts, but  CMD can be  docker run replaced by the following command line parameters.

FROM alpine:latest
RUN apk add --update curl && rm -rf /var/cache/apk/*
CMD ["curl"]

ENTRYPOINT

Configure the command to run when the container starts, and cannot be replaced by default parameters.

FROM alpine:latest
RUN apk add --update curl && rm -rf /var/cache/apk/*
ENTRYPOINT ["curl"]

It seems that the two commands are almost duplicate instructions. In fact, users can override the default command provided by the CMD command through the command line parameters; using the ENTRYPOINT command, the parameters added on the command line will be appended to the parameter list of the curl command.

Create a curl directory, save the above code into the Dockerfile in the curl directory, then enter the curl directory to build a mirror and start a container:

mkdir curl && cd curl
cat > Dockerfile <<EOF
FROM alpine:latest
RUN apk add --update curl && rm -rf /var/cache/apk/*
ENTRYPOINT ["curl"]
EOF
docker build -t curl .
docker run --rm curl http://www.baidu.com

The output is:

Good job! Everything works fine.

The image is only 7.73MB, as shown below:

In this example, we use the ENTRYPOINT directive as the "entry" to the container. As for the CMD command, the official definition is the default executable of a container:

The main purpose of aCMDis to provide defaults for an executing container.These defaults can include an executable, or they can omit the executable, in which case you must specify an ENTRYPOINTinstruction as well.

Both of these instructions are used to specify the command to run when the container starts, and using one of them alone can achieve most use cases. But Docker provides them at the same time. In order not to confuse them in use, this article tries to clarify their usage. Without further ado, let's take a look at the detailed introduction of Part 2.


#Part 2 The essential difference between CMD and ENTRYPOINT

CMD and ENTRYPOINT instructions have fundamental differences in how they work, and they suit different applications, environments, and scenarios.

When there are parameters in the CLI command docker run,

  1. The daemon will ignore CMD instructions defined in the Dockerfile.
  2. ENTRYPOINT is not ignored and arguments on the command line are appended to the argument list for the command specified by ENTRYPOINT.

Next, let's take a closer look at these two directives.

Docker CMD

Provides a default command to execute for the container.

A Dockerfile can have one or more CMD instructions, in case of multiple CMD instructions, all but the last one will be ignored.

For example:

mkdir cmd && cd cmd
cat > Dockerfile <<EOF
FROM ubuntu
CMD ["/bin/echo", "1"]
CMD ["/bin/echo", "2"]
EOF
docker build -t cmd .
docker run --rm cmd

The output is:

If we docker runadd parameters to the command, it will override the default CMD command, the syntax is:

docker run IMAGE [COMMAND] [ARG...]

For example:

docker run cmd hostname

The output is:

Therefore, the best time to use the CMD command is:

Provides the container with a default command to execute when the user enters no arguments on the command line.

This directive ensures that the container is running by starting the application as soon as the container image is running. The reason for this is that the CMD command loads the base image as soon as the container starts.

Docker ENTRYPOINT

In a Dockerfile, the ENTRYPOINT directive is used to set an executable to always run when starting a container. Unlike the CMD command, the ENTRYPOINT command cannot be ignored or rewritten (accurately speaking, the docker runfollowing command line parameters will not override the ENTRYPOINT command; docker runit --entrypointcan override the command set by ENTRYPOINT in the Dockerfile), even if the command line parameter is declared when the container is running .

The Docker ENTRYPOINT command supports two modes of writing: shell and exec:

  • Exec mode: ENTRYPOINT ["executable", "parameter1", "parameter2"]
  • Shell mode: ENTRYPOINT command parameter1 parameter2

First an example:

mkdir entrypoint && cd entrypoint
cat > Dockerfile <<EOF
FROM ubuntu
ENTRYPOINT ["/bin/echo"]
EOF
docker build -t entrypoint .
docker run --rm entrypoint

The output is:

Empty, nothing, which is what we expect since no echoarguments are passed to the command.

Run a new container, adding parameters  $HOME:

docker run --rm entrypoint $HOME

The output is:

Conclusion: When the ENTRYPOINT command is in exec mode, the parameters specified on the command line will be added as parameters to the parameter list of the command specified by ENTRYPOINT.

So, when the ENTRYPOINT command is in shell mode, what happens to the command-line arguments?

Modify the Dockerfile, create the image and run the container:

cat > Dockerfile <<EOF
FROM ubuntu
ENTRYPOINT /bin/echo
EOF
docker build -t entrypoint .
docker run --rm entrypoint

The output is empty when no parameters are added:

Add parameters $HOME:

docker run --rm entrypoint $HOME

The output is still empty:

In shell mode, pass parameters through CMD, can the ENTRYPOINT command be received, let’s try again:

cat > Dockerfile <<EOF
FROM ubuntu
ENTRYPOINT /bin/echo
CMD $HOME
EOF
docker build -t entrypoint .
docker run --rm entrypoint

The output is still empty:

Conclusion: When the ENTRYPOINT command is in shell mode, the command line and CMD parameters are ignored.

Generally, we will use the exec mode of ENTRYPOINT as the default execution command after the docker container is started. It contains the invariant part and requires other parameters, which can be added to the command line when docker runrunning the container.

Using CMD and ENTRYPOINT at the same time

CMD and ENTRYPOINT are two instructions with similar functions, and some cases may need to use their combined instructions in the Dockerfile. Commands can be defined using the ENTRYPOINT directive, while parameters can be defined using the CMD.

example:

mkdir cmd-entrypoint && cd cmd-entrypoint
cat > Dockerfile <<EOF
FROM ubuntu
ENTRYPOINT ["echo", "Hello"]
CMD ["Darwin"]
EOF
docker build -t cmd-entrypoint .
docker run --rm cmd-entrypoint

The output is:

Appending a command with an argument such as Hawking will override the CMD command and execute only the ENTRYPOINT command with the CLI parameter as an argument. For example:

docker run --rm cmd-entrypoint Hawking

The output is:

This is because the ENTRYPOINT directive cannot be ignored, and when using CMD, command line arguments override this directive.

Use ENTRYPOINT or CMD

Both ENTRYPOINT and CMD are essential for building and running Dockerfiles, it all depends on the usage scenario, in general:

  1. Use the RUN command to install applications and software packages and build images.
  2. Always need to execute a command to build an executable Docker image, choose the ENTRYPOINT command.
  3. The CMD command is best suited as an additional set of parameters to the default command, while allowing docker runthe command line to replace the default parameters.

Also note that in the Dockerfile:

  1. If there are multiple ENTRYPOINT directives, the last one overrides the previous ones
  2. If there are multiple CMD commands, the last one will override the previous ones
  3. At least one ENTRYPOINT instruction or CMD instruction

#Part 3 Shell mode and exec mode

First, we need to understand how the Docker daemon processes instructions after they have been delivered.

All Docker command commands either belong to shell mode or exec mode. We understand the commands in these two modes through a simple Dockerfile example:

1 Shell mode

As the name suggests, commands in the shell form start processes running in the shell, which are equivalent to  /bin/sh -c "task command" executing task commands in the same way.

The syntax is:

<instruction><command>

See the example below:

FROM ubuntu
CMD top

Create the shell-command-form directory, save the above code into the Dockerfile in the shell-command-form directory, build the image, and start a container:

mkdir shell-command-form && cd shell-command-form
cat > Dockerfile <<EOF
FROM ubuntu
CMD top
EOF
docker build -t shell-command-form .
docker run -itd --name shell-command-form-test shell-command-form 

Then look at the process ID in the container:

docker exec shell-command-form-test ps aux 

The command executed by process 1 is unexpectedly , and the process ID of the command /bin/sh -c topwe specified is 7. topThe reason why Docker is arranged in this way is to allow the commands or scripts we execute to get the environment variables .

By running  docker ps the command, it can also be seen that Docker first runs /bin/sh -c top:

Define environment variables in Dockerfile

The syntax is:

ENV <key> <value>

Define an environment variable whose key is name:

ENV name Darwin
CMD /bin/echo "Welcome, $name"

Based on the examples above, build the image and start a container:

docker build -t darwin .
docker run --rm darwin

The output is:

This form of command validates before returning results, often causing performance bottlenecks. Therefore, shell mode is generally not the preferred mode unless there is a specific need for command/environment validation.

2 Executable mode

Different from the Shell mode, the commands written in the Executable command mode directly run the executable script without being verified and processed by the shell.

The syntax is as follows:

<instruction>[“executable”, “parameter 1”, “parameter 2”, …]

example:

RUN ["yum", "-y", "update"]
CMD ["yum", "install", "-y", "ebtables"]

Execute commands with environment variables in exec mode:

cat > Dockerfile <<EOF
FROM ubuntu
ENV name Darwin
CMD ["/bin/echo", "Welcome, \$name"]
EOF
docker build -t executable-command-form .
docker run --rm executable-command-form

The output is:

This proves that Docker did not replace the user-defined environment variables with the corresponding values ​​during the running process.

Will the environment variables of the system be output in exec mode? We print the HOSTNAME in the Linux system environment variable through the CMD command in exec mode:

cat > Dockerfile <<EOF
FROM ubuntu
CMD ["/bin/echo", "\$HOSTNAME"]
EOF
docker build -t executable-command-form .
docker run --rm executable-command-form

The output is:

So far, the following conclusions have been drawn:

In exec mode, related commands will not be executed through the shell, so system environment variables like $HOSTNAME cannot be obtained.

Then in exec mode, what should I do if I want to output custom environment variables and system environment variables?

It is to execute the shell in this mode to obtain environment variables:

cat > Dockerfile <<EOF
FROM ubuntu
ENV name Darwin
CMD ["/bin/sh", "-c", "echo \$name && echo \$HOSTNAME"]
EOF
docker build -t executable-command-form .
docker run --rm executable-command-form

The output is:

So far, the values ​​of custom environment variables and system environment variables have been perfectly obtained.


Using exec mode and shell mode, the difference between executing ENTRYPOINT and CMD


reference:

Dockerfile reference​docs.docker.com/engine/reference/builder/#cmd​Edit

Dockerfile reference​docs.docker.com/engine/reference/builder/#entrypoint​Edit

Docker CMD vs ENTRYPOINT: What’s The Difference & How To Choose​www.bmc.com/blogs/docker-cmd-vs-entrypoint/​编辑

Guess you like

Origin blog.csdn.net/chuixue24/article/details/132181159