$ cat docker-entrypoint.sh
bash
#!/usr/bin/env sh
set -e
loglevel="${loglevel:-}"
USERID=$(id -u)
# if the first argument look like a parameter (i.e. start with '-'), run Envoy
if [ "${1#-}" != "$1" ]; then
set -- envoy "$@"
fi
if [ "$1" = 'envoy' ]; then
# set the log level if the $loglevel variable is set
if [ -n "$loglevel" ]; then
set -- "$@" --log-level "$loglevel"
fi
fi
if [ "$ENVOY_UID" != "0" ] && [ "$USERID" = 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
exec su-exec envoy "${@}"
else
exec "${@}"
fi
这个脚本 docker-entrypoint.sh
是一个 Docker 容器的入口脚本,用于设置和执行 Envoy 代理服务器。下面是对脚本的逐行解释:
-
#!/usr/bin/env sh
:这是 shebang 行,告诉系统使用哪个解释器来执行脚本。这里使用的是sh
shell。 -
set -e
:这个命令告诉 shell 在任何语句的执行结果不是 true 时就终止执行,这有助于捕获错误。 -
loglevel="${loglevel:-}"
:这行设置了loglevel
变量的值,如果环境变量loglevel
已经设置,则使用其值,否则为空。 -
USERID=$(id -u)
:获取当前用户的用户ID。 -
if [ "${1#-}" != "$1" ]; then
:检查脚本的第一个参数是否以连字符-
开头。如果是,说明可能是一个选项参数。 -
set -- envoy "$@"
:如果第一个参数是选项,将envoy
添加到参数列表的前面,并保留所有原始参数。 -
if [ "$1" = 'envoy' ]; then
:检查第一个参数是否是envoy
,即是否要启动 Envoy 代理。 -
if [ -n "$loglevel" ]; then
:如果loglevel
变量已经设置,并且不为空。 -
set -- "$@" --log-level "$loglevel"
:将--log-level
选项和loglevel
值添加到参数列表中。 -
if [ "$ENVOY_UID" != "0" ] && [ "$USERID" = 0 ]; then
:如果ENVOY_UID
环境变量设置且不等于 0,并且当前用户是 root 用户(用户ID 为 0)。 -
usermod -u "$ENVOY_UID" envoy
:改变用户envoy
的用户ID为ENVOY_UID
。 -
groupmod -g "$ENVOY_UID" envoy
:改变用户envoy
的组ID为ENVOY_GID
。 -
chown envoy:envoy /dev/stdout /dev/stderr
:确保envoy
用户拥有对标准输出和标准错误的所有权,以便能够写入容器日志。 -
exec su-exec envoy "${@}"
:使用su-exec
以envoy
用户身份执行参数列表中的命令。 -
else
:如果上面的条件不满足,即不是以 root 用户身份运行,或者ENVOY_UID
没有设置。 -
exec "${@}"
:直接执行参数列表中的命令。
这个脚本的主要目的是在 Docker 容器启动时,根据提供的参数和环境变量配置 Envoy 代理,并以适当的用户身份执行它。如果容器以 root 用户身份启动,并且定义了 ENVOY_UID
和 ENVOY_GID
,则会更改 Envoy 用户的 UID 和 GID,并以该用户身份执行 Envoy。如果没有定义这些环境变量,或者不是以 root 用户身份启动,它将直接执行 Envoy 或其他传递的命令。