What does set -e and exec "$@" do for docker entrypoint scripts?

ShellDocker

Shell Problem Overview


I've noticed that many entrypoint.sh scripts for docker do something like this:

#!/bin/bash
set -e

... code ...

exec "$@"

What are the set -e and the exec "$@" for?

Shell Solutions


Solution 1 - Shell

It basically takes any command line arguments passed to entrypoint.sh and execs them as a command. The intention is basically "Do everything in this .sh script, then in the same shell run the command the user passes in on the command line".

See:

Solution 2 - Shell

set -e sets a shell option to immediately exit if any command being run exits with a non-zero exit code. The script will return with the exit code of the failing command. From the bash man page:

> set -e: > > Exit immediately if a pipeline (which may consist of a single simple command), a list, or a compound command (see SHELL > GRAMMAR above), exits with a non-zero status. The shell does not exit > if the command that fails is part of the command list immediately > following a while or until keyword, part of the test following the if > or elif reserved words, part of any command executed in a && or || > list except the command following the final && or ||, any > command in a pipeline but the last, or if the command's return value > is being inverted with !. If a compound command other than a subshell > returns a non-zero status because a command failed while -e was being > ignored, the shell does not exit. A trap on ERR, if set, is executed > before the shell exits. This option applies to the shell environment > and each subshell environment separately (see COMMAND EXECUTION > ENVIRONMENT above), and may cause subshells to exit before executing > all the commands in the subshell. > > If a compound command or shell function executes in a context where > -e is being ignored, none of the commands executed within the compound command or function body will be affected by the -e setting, even if > -e is set and a command returns a failure status. If a compound command or shell function sets -e while executing in a context where > -e is ignored, that setting will not have any effect until the compound command or the command containing the function call > completes.


exec "$@" is typically used to make the entrypoint a pass through that then runs the docker command. It will replace the current running shell with the command that "$@" is pointing to. By default, that variable points to the command line arguments.

If you have an image with an entrypoint pointing to entrypoint.sh, and you run your container as docker run my_image server start, that will translate to running entrypoint.sh server start in the container. At the exec line entrypoint.sh, the shell running as pid 1 will replace itself with the command server start.

This is critical for signal handling. Without using exec, the server start in the above example would run as another pid, and after it exits, you would return to your shell script. With a shell in pid 1, a SIGTERM will be ignored by default. That means the graceful stop signal that docker stop sends to your container, would never be received by the server process. After 10 seconds (by default), docker stop would give up on the graceful shutdown and send a SIGKILL that will force your app to exit, but with potential data loss or closed network connections, that app developers could have coded around if they received the signal. It also means your container will always take the 10 seconds to stop.

Note that with shell commands like shift and set --, you can change the value of "$@". E.g. here's a short part of a script that removes the /bin/sh -c "..." from the command that can appear if you use docker's shell syntax for CMD:

# convert `/bin/sh -c "server start"` to `server start`
if [ $# -gt 1 ] && [ x"$1" = x"/bin/sh" ] && [ x"$2" = x"-c" ]; then
  shift 2
  eval "set -- $1"
fi

....

exec "$@"

Solution 3 - Shell

set -e - exit script if any command fails (non-zero value)

exec "$@" - will redirect input variables, see more here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNathanView Question on Stackoverflow
Solution 1 - ShellMatthewView Answer on Stackoverflow
Solution 2 - ShellBMitchView Answer on Stackoverflow
Solution 3 - ShellagilobView Answer on Stackoverflow