[Reprint] Dockerfile: the difference between the CMD and ENTRYPOINT

Dockerfile: the difference between the CMD and ENTRYPOINT

 

In our review Dockerfile of official documents , the possible discovery of a number of repeat orders (at least appear to do things almost), I have above analyzed the difference between ADD and COPY commands (they function similar), and now we analyze another 2 command, and their functions are very similar, it is CMD and ENTRYPOINT.

 

Although ENTRYPOINT and execute a command in CMD are docker image inside, but they have some subtle differences. In most cases, you just have to choose between these two can be a call, but they have more advanced applications , CMD and ENTRYPOINT used in combination, completed more feature-rich.

 

ENTRYPOINT or CMD?

 

Basically, ENTRYPOINT and CMD is to let the user specify an executable program, the executable program starts automatically after container is started. In fact, if you want to produce their own programs to run automatically mirrored (no later docker run adding command line commands specified to run), you have to Dockerfile inside, or use the CMD command ENTRYPOINT

 

For example, the implementation does not call ENTRYPOINT run a CMD or a docker mirror must return an error

 

$ docker run alpine
FATA[0000] Error response from daemon: No command specified

 

Most Linu release base image which calls CMD command, execute / bin / sh or / bin / bash started after the specified container. Such a mirrored boot into the default interactive shell

 

Annotation: three different Linux images (ubuntu, busybox, debian) are Dockerfile last call CMD '/ bin / bash'

 

After starting the Linux distribution base container, called by default shell program, in line with most people's habits.

However, as a developer, you want to start after docker mirror, automatically run other programs. So, you need to explicitly specify a specific command or ENTRYPOINT CMD command.

 

Cover (Overrides)

 

In writing Dockerfile, ENTRYPOINT or CMD command will automatically overwrite the previous ENTRYPOINT or CMD command.

In docker Mirror operation, the user can also specify the specific command in the command, the command Dockerfile in the cover.

For example, we wrote such a Dockerfile:

FROM ubuntu:trusty
CMD ping localhost 

 

If you build a new image based on this Dockerfile, called demo

$ docker run -t demo
PING localhost (127.0.0.1) 56(84) bytes of data. 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.051 ms 64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.038 ms ^C --- localhost ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.026/0.032/0.039/0.008 ms

As can be seen in their own ping command is executed after docker start, but we can at the command line to start docker mirror, perform other command-line parameters to override the default CMD

 

$ docker run demo hostname
6c1573c0d4c0

 

After docker start, and did not execute the ping command, but run the hostname command

 

And CMD similar default ENTRYPOINT also docker run time can also be covered. At run time, with --entrypoint override the default ENTRYPOINT

 

$ docker run --entrypoint hostname demo
075a2fa95ab7 

 

Because CMD command can easily be way docker run command coverage, so if you want your docker mirror functional and flexible enough, it is recommended to call CMD command in Dockerfile in. For example, you might have a generic Ruby mirror, when the mirror starts default execution irb ( CMD irb ).

If you want to use this image Ruby execute any Ruby script, you only need to perform this sentence:

 

docker run ruby ruby -e 'puts "Hello"

Annotation: ruby ​​-e 'puts "Hello" covers irb command

 

On the contrary, the different roles ENTRYPOINT, if you want your docker mirror only performs a specific program, you do not want users to freely cover the default program in the implementation of docker run. ENTRYPOINT recommended.

 

Docker in many cases be used to package a program. Imagine that you have a script in python to achieve, you need to release the python program. If this package docker python program, your end users do not need to install python interpreter the library dependencies and python. you can put all the tools rely on packaged into docker mirror, and then use

ENTRYPOINT point to your Python script itself. Of course, you can also use the CMD command points Python scripts, but usually ENTRYPOINT can show your docker mirror just to execute this python script, end users do not want to do other operations with the docker image.

 

Later will explain how a combination of ENTRYPOINT and CMD. They own unique role will be even more evident.

 

Shell vs. Exec

 

 

ENTRYPOINT command CMD and supports two different wording: shell representation and notation exec The following example uses the notation shell:

CMD executable  param1 param2

When using the shell notation, the command line to run the program as a subroutine sh program syntax to call docker with / bin / sh -c If we look at docker run with a docker ps command, you can see the actual operation is / bin / sh -c command

 

$ docker run -d demo
15bfcddb11b5cde0e230246f45ba6eeb1e6f56edb38a91626ab9c478408cb615

$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED
15bfcddb4312 demo:latest "/bin/sh -c 'ping localhost'" 2 seconds ago 

We run the demo mirror again, you can see the actual operation of the command is / bin / sh -c 'ping localhost'.

 

Although the shell notation seems to work well, but it is in fact on the existence of some small problems if we look at the command being run by docker ps command, there will be the following output:

$ docker exec 15bfcddb ps -f
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 20:14 ? 00:00:00 /bin/sh -c ping localhost
root 9 1 0 20:14 ? 00:00:00 ping localhost
root 49 0 0 20:15 ? 00:00:00 ps -f 

 

1 PID for the process of the ping command is not defined in Dockerfile inside, but / bin / sh command. If you send any POSIX signal from the outside to the docker container, as / bin / sh command does not forward the message to the actual operation of the ping command you can not security too close docker container (refer to more detailed documentation: Gracefully Stopping Docker containers ).

Annotation: ping In the example above, if the form of the CMD with the shell, the user presses ctrl-c can not stop the ping command, as ctrl-c signal is not forwarded to the ping command

 

In addition to the above problem, if you want to build a super small docker mirror, the mirror even the shell program can not. Shell representation can not meet this requirement. If your image there is no / bin / sh, docker container to You can not run.

 

A better option is to use the exec form of the ENTRYPOINT/CMD instructions which looks like this:

 

A better choice is a method using exec:

CMD ["executable","param1","param2"] 

 

 

Let's change our Dockerfile from the example above to see this in action:

 

CMD command behind with a syntax similar to JSON representation command to be executed. This usage tells docker not need to call / bin / sh execute the command.

 

We'll revise Dockerfile, use exec notation:

FROM ubuntu:trusty
CMD ["/bin/ping","localhost"] 

 

Re-build the mirror, with the command to check the effect docker ps:

$ docker build -t demo .
[truncated]

$ docker run -d demo
90cd472887807467d699b55efaf2ee5c4c79eb74ed7849fc4d2dbfea31dce441

$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED
90cd47288780 demo:latest "/bin/ping localhost" 4 seconds ago 

 

Now do not start / bin / sh command, but directly run / bin / ping command, PID ping command is 1. Whether you are using a ENTRYPOINT or CMD command, strongly recommended exec representation,

 

 

And CMD combination ENTRYPOINT

 

Previously discussed only with ENTRYPOINT or default to run the program one of CMD specified image, but in some cases, a combination of ENTRYPOINT and CMD can play a greater role.

And a combination of EntryPoint CMD, ENTRYPOINT specify the default run command, CMD specifies the default operating parameters of the following examples:

 

FROM ubuntu:trusty
ENTRYPOINT ["/bin/ping","-c","3"] CMD ["localhost"] 

 

According to the above constructed image Dockerfile, without any parameters docker run command Run

$ docker build -t ping .
[truncated]

$ docker run ping
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.025 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.038 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.051 ms

--- localhost ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.025/0.038/0.051/0.010 ms

$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED
82df66a2a9f1 ping:latest "/bin/ping -c 3 localhost" 6 seconds ago 

 

Above is ENTRYPOINT command CMD and the splicing instruction. When ENTRYPOINT exist and CMD, the CMD command Docker after ENTRYPOINT command spliced, the splicing command is the command executed last. However, since the above said docker run command when the line executes, you can cover the CMD command value if you want the image to start after docker not ping localhost, but this can ping other servers ,, execute docker run.:

 

$ docker run ping docker.io
PING docker.io (162.242.195.84) 56(84) bytes of data.
64 bytes from 162.242.195.84: icmp_seq=1 ttl=61 time=76.7 ms
64 bytes from 162.242.195.84: icmp_seq=2 ttl=61 time=81.5 ms
64 bytes from 162.242.195.84: icmp_seq=3 ttl=61 time=77.8 ms

--- docker.io ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 76.722/78.695/81.533/2.057 ms

$ docker ps -l --no-trunc
CONTAINER ID IMAGE COMMAND CREATED
0d739d5ea4e5 ping:latest "/bin/ping -c 3 docker.io" 51 seconds ago

 

Run docker mirror, feel and perform any other program you specify the program is no different --- (ping) to execute the ping command and specify the parameters required.

Noting -C 3 parameters, this parameter indicates the ping request only three times, this parameter is included in ENTRYPOINT which corresponds to a hard-coded docker mirror. Docker each time the image will take this parameter and the parameter can not be covered CMD .

 

 

 

Always use Exec notation

Combination ENTRYPOINT and CMD imperative to ensure that you will use the Exec notation. If one is using Shell representation, or a representation is Shell, the other is the Exec notation, you never get what you expected Effect.

 

The following table lists if Shell and Exec notation indicates the mixing method, the resulting command line, you can see if there are Shell indicate the presence of law, it is difficult to get the right effect:

 

Dockerfile    Command

ENTRYPOINT /bin/ping -c 3 CMD localhost /bin/sh -c '/bin/ping -c 3' /bin/sh -c localhost   ENTRYPOINT ["/bin/ping","-c","3"] CMD localhost /bin/ping -c 3 /bin/sh -c localhost  ENTRYPOINT /bin/ping -c 3 CMD ["localhost"]" /bin/sh -c '/bin/ping -c 3' localhost  ENTRYPOINT ["/bin/ping","-c","3"] CMD ["localhost"] /bin/ping -c 3 localhost

 

It is seen from above, and CMD are used only ENTRYPOINT Exec notation, to get the desired results

 

in conclusion

 

If you want your docker image to do the real work, will be used in Dockerfile in ENTRYPOINT or CMD. Note, however, these two commands are not mutually exclusive. In many cases, you can combine ENTRYPOINT and CMD command to enhance the end user experience.

Guess you like

Origin www.cnblogs.com/jinanxiaolaohu/p/11646097.html