Docker Entrypoint Script

I have a post Shell Arguments Format talked about exec "$@" (当时并没有在意为什么在docker中这么使用), the script docker-entrypoint.sh is a very common and flexible way to accept different parameters when start docker container and run application as PID 1, this allows the application to receive any Unix signals sent to the container (之前遇到过这个问题, 非PID 1的进程在对container 的终止signal 没有反应).

See this docker best practice about entrypoint: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#entrypoint

The same pattern in envoy image, see this docker-entrypoint.sh link:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/usr/bin/env sh
set -e

# shell parameter expansion
# if LOGLEVEL is null or unset, then assign null to it
# env variable can set from `-e` with docker run
loglevel="${LOGLEVEL:-}"

# if the first argument looks like a parameter (i.e. start with '-'), run Envoy
# ${1#-} 的意思是对于第一个positional parameter, 是不是以-开头
# ${1#-} expand 的结果是去掉最短的match部分
if [ "${1#-}" != "$1" ]; then
# re-set $@ value
# see below explanation
set -- envoy "$@"
fi

# have CMD ['envoy'] in dockerfile
# this is the default parameter to entrypoint
if [ "$1" = 'envoy' ]; then
# set the log level if the $loglevel variable is set
if [ -n "$loglevel" ]; then
# 更新位置参数
set -- "$@" --log-level "$loglevel"
fi
fi

# ENVOY_UID is the environment variables you specified
# to set envoy userid/group
if [ "$ENVOY_UID" != "0" ]; then
if [ -n "$ENVOY_UID" ]; then
usermod -u "$ENVOY_UID" envoy
fi
if [ -n "$ENVOY_GID" ]; then
groupmod -g "$ENVOY_GID" envoy
fi
# Ensure the envoy user is able to write to container logs
chown envoy:envoy /dev/stdout /dev/stderr

# su-exec switch user exec
# https://github.com/ncopa/su-exec
su-exec envoy "${@}"
else
# becomes PID 1
# 注意有double quote
exec "${@}"
fi

For example:

1
2
3
4
5
6
7
8
# start as bash
docker run --rm -it envoy_image_name:tag bash

# pass parameters `--help` and run
docker run --rm -it envoy_image_name:tag --help

# run as default CMD `envoy` with ENTRYPOINT
docker run --rm -it -e ENVOY_UID=1001 -e LOGLEVEL="info" envoy_image_name:tag

The new thing to me is set --, see this question: What does “set --” do in this Dockerfile entrypoint?

The set -- command sets the positional parameters and link new tokens with existing position parameters, The -- is the standard “don’t treat anything following this as an option”,也就是说这是要排列位置参数了,而不是重置位置参数:

1
2
3
4
5
6
7
8
set a b c
# output "a b c"
echo $1 $2 $3

# 相当于$@ = newToken "$@"
set -- newToken "$@"
# it actually exec "newToken a b c"
exec "${@}"

Nginx Entrypoint

Let’s see one more about nginx docker entrypoint and explain:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/bin/sh
# vim:sw=4:ts=4:et

set -e

# if quiet log, then redirect to /dev/null
# otherwise redirect to 1 (stdout)
if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
# link file descriptor 3(additional) to 1 (stdout)
# 3 is file descriptor see below explanation

# exec can preserve the setting
exec 3>&1
else
exec 3>/dev/null
fi
# why use new fd 3: 3 is used by echo later, easy to manage redirect to where

# -o: or
if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then
# redirect message from 1 (implicitly) to 3 (stdout in essence)
# echo >&3 facilitate reading, see below explanation
echo >&3 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"

echo >&3 "$0: Looking for shell scripts in /docker-entrypoint.d/"
find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do
case "$f" in
*.sh)
# -x: file exists and executable
if [ -x "$f" ]; then
echo >&3 "$0: Launching $f";
"$f"
else
echo >&3 "$0: Ignoring $f, not executable";
fi
;;
*) echo >&3 "$0: Ignoring $f";;
esac
done

echo >&3 "$0: Configuration complete; ready for start up"
else
echo >&3 "$0: No files found in /docker-entrypoint.d/, skipping configuration"
fi
fi

# process replacement
exec "$@"

Explanation:

0%