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
とかで書き換えると設定が読み込まれないのか...
-o
オプション
ifの中の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コンテナをいじる際はこのページを参照する。