nginxコンテナのdocker-entrypoint.shは何をしているのか
これはなに?
nginxの公式コンテナイメージを使用しており、
起動時にシェルスクリプトを実行したいときは、/docker-entrypoint.dに実行したいシェルスクリプトを格納すれば動作します。
ではなぜ/docker-entrypoint.dに格納するのでしょうか。
同じ階層にある/docker-entrypoint.shに秘密が書かれてそうなので読んでみました。
実際にシェルスクリプトを動かす例は以下にメモしてあります。
確認
~$ docker inspect nginx:latest | jq '.[].ContainerConfig.Entrypoint'
[
"/docker-entrypoint.sh"
]
docker-entrypoint.shの中身
コード
set -e
役割
エラーした際にスクリプトを停止する
コード
entrypoint_log() {
if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
echo "$@"
fi
}
役割①
nginxイメージの説明に記載がありました。
Ver1.19.0以降はentrypointの詳しいログがデフォルトで有効になっており、
NGINX_ENTRYPOINT_QUIET_LOGS環境変数を設定するとそれを抑制できるようです。
Since version 1.19.0, a verbose entrypoint was added. It provides information on what's happening during container startup. You can silence this output by setting environment variable NGINX_ENTRYPOINT_QUIET_LOGS:
役割②
entrypoint_log関数を作成しています。
NGINX_ENTRYPOINT_QUIET_LOGSの文字列の長さが0(空)であれば、渡された文字列を出力します。
例えばこの文字列が出力されるわけですね
entrypoint_log "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"
コード
if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then
...
fi
役割
docker-entrypoint.shの第一引数がnginxかnginx-debugであれば処理が進むということですね。
CMDとかで書き換えると設定が読み込まれないのか...
ifの中の-oオプション
or条件を表すそうです。引数の候補が複数あるのに対応できるんですね
man [で見れます
EXPRESSION1 -o EXPRESSION2
either EXPRESSION1 or EXPRESSION2 is true
コード
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then
...
else
entrypoint_log "$0: No files found in /docker-entrypoint.d/, skipping configuration"
fi
役割
/docker-entrypoint.d/配下にファイルがあれば処理を進め、なければelseに飛びます
readで標準出力を変数に格納しているのは余計なログを出さないため?
コード
entrypoint_log "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"
entrypoint_log "$0: Looking for shell scripts in /docker-entrypoint.d/"
find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do
# 処理
done
役割①
/docker-entrypoint.d/配下にファイルが存在する場合、entrypoint_log関数を実行します。
役割②
/docker-entrypoint.d/のファイルをfindで検索し、結果をreadで1つずつ読み込みます。
読み込んだファイルに処理を実行し、それをファイル数分繰り返します。
コード
case "$f" in
*.envsh)
if [ -x "$f" ]; then
entrypoint_log "$0: Sourcing $f";
. "$f"
else
# warn on shell scripts without exec bit
entrypoint_log "$0: Ignoring $f, not executable";
fi
;;
*.sh)
if [ -x "$f" ]; then
entrypoint_log "$0: Launching $f";
"$f"
else
# warn on shell scripts without exec bit
entrypoint_log "$0: Ignoring $f, not executable";
fi
;;
*) entrypoint_log "$0: Ignoring $f";;
esac
役割
先述のreadで読み込んだファイル名によって処理を変えます。
ファイル名が*.envshの場合
ファイルが実行可能であれば. <ファイル名>(ドットコマンド)を実行し、変数を読み込む。
実行不可である場合その旨をentrypoint_logで出す。
ファイル名が*.shの場合
ファイルが実行可能であれば実行する。
実行不可である場合その旨をentrypoint_logで出す。
それ以外
entrypoint_log "$0: Ignoring $f"を実行
簡潔にまとめ
- 詳細ログをみたいときは
NGINX_ENTRYPOINT_QUIET_LOGSを設定する - 実行権限を与えたスクリプトを
/docker-entrypoint.d/に配置すれば、/docker-entrypoint.shで実行してくれる
所感
シェルスクリプトを読む良い練習になりました。
nginxコンテナをいじる際はこのページを参照する。