現在、自宅環境には以下のコンテナを起動させて運用をしている。
- プロキシ用コンテナ : Squid
- DNS用コンテナ : Unbound
- メール用コンテナ : Postfix
この中でSquidとPostfixにおいて、docker stop
やdocker-compose stop
などで停止処理した際に、停止はするもののExit 137
というExitコードになる事象が発生した。
※以下★箇所。
# docker-compose stop
Stopping centos-postfix ... done
Stopping centos-unbound ... done
Stopping centos-squid ... done
# docker-compose ps
Name Command State Ports
------------------------------------------------------------------
centos-postfix /startup.sh Exit 137 ←★
centos-squid /bin/sh -c /usr/sbin/squid ... Exit 137 ←★
centos-unbound /usr/sbin/unbound -d Exit 0
調べたところ、SquidとPostfixのコンテナで、それぞれExit 137
となる原因が違っていた。
今回は、Docker停止時にExit 137
になる原因の説明と解消方法を記載する。
環境
- DockerホストOS : CentOS 8.2
- Docer : 19.03.14
- Docker Compose : 1.27.4
Dockerのコンテナ停止時にExit 137
になる理由
そもそもコンテナがExit 137
で停止する理由について記載する。
Dockerのデフォルト設定ではコンテナ停止を行う際に、まずPID 1のプロセスに対してSIGTERM
のシグナルを送信しプロセス終了を促す。Dockerは10秒待機し、それでもプロセスが終了しない場合は、SIGKILL
シグナルにて強制終了を行う。
Exit 137
はSIGKILL
によるプロセスの終了を実施した際に出力されるExitコードとなる。
SquidコンテナのExit 137
の原因と解消方法
SquidのコンテナがExit 137
となる理由は、Squidのキャッシュをディスクに書き込みするための待機時間としてデフォルトで30秒待機してから停止が完了するためである。Dockerは10秒でSIGKILL
にて強制終了をしてしまうため、通常のSIGTERM
による停止処理が間に合わない。
そのため、解消方法としては、Docker側のコンテナ停止処理時のタイムアウトを30秒より多い時間に延長するか、Squid側の待機時間を10秒未満とするか、どちらかの手法で対応できる。今回は後者にて対応する。
Squidの停止処理の待機時間は、shutdown_lifetime
というパラメータで設定できるので、デフォルトの30秒から5秒に変更する。
※参考:squid : shutdown_lifetime configuration directive
具体的にはsquid.conf
に以下を追加すればよい。
shutdown_lifetime 5 seconds
設定変更した内容でコンテナを再作成し、docker stop
コマンドでコンテナを停止してみたところ、以下の通り、Exit 0
で正常に停止できていることがわかる。
# docker stop centos-squid
centos-squid
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bb34a12ed7bc centos-squid:1 "/usr/sbin/squid -N …" 13 hours ago Exited (0) 5 seconds ago centos-squid
PostfixコンテナのExit 137
の原因と解消方法
Postfixのコンテナでは、maillog
にメール送受信のログを出力させるためにrsyslogを起動させている。この際に、以下のようなstartup.sh
というラッパースクリプトを作成して、rsyslogとPostfixの起動を実現していた。
#!/bin/bash
/usr/sbin/rsyslogd
/usr/sbin/postfix start-fg
上記スクリプトでプロセスを起動した際のコンテナにおけるps
の結果を以下に記載する。Postfixの一部プロセスのPID/PPIDが1以外の番号で動作していることがわかる。
# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 05:46 ? 00:00:00 /bin/bash /startup.sh
root 7 1 0 05:46 ? 00:00:00 /usr/sbin/rsyslogd
root 9 1 0 05:46 ? 00:00:00 /bin/sh /usr/libexec/postfix
root 76 9 0 05:46 ? 00:00:00 /usr/libexec/postfix/master
postfix 77 76 0 05:46 ? 00:00:00 pickup -l -t unix -u
postfix 78 76 0 05:46 ? 00:00:00 qmgr -l -t unix -u
postfix 79 76 0 05:46 ? 00:00:00 smtpd -n smtp -t inet -u -o
postfix 81 76 0 05:46 ? 00:00:00 tlsmgr -l -t unix -u
root 85 0 5 05:52 pts/0 00:00:00 bash
root 98 85 0 05:52 pts/0 00:00:00 ps -ef
前述したとおり、Dockerは、PID 1のプロセスに対してSIGTERM
のシグナルを送信するが、PID/PPIDが1以外のプロセスが存在することにより停止処理が失敗することが、Exit 137
となる原因となる。
本事象を解消させるために、ラッパースクリプトのPostfixの起動コマンドにexec
を付与することで解消する (★箇所)。exec
コマンドを使うことで、すべてのプロセスが、もとのラッパースクリプトと同じPID/PPID、すなわちPID/PPIDが1で動作するようになる。
#!/bin/bash
/usr/sbin/rsyslogd
exec /usr/sbin/postfix start-fg ★
実際にコンテナでps
を実行した結果は以下の通りとなる。Postfix関連のプロセスはすべてPID/PPIDが1となっている。
# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 05:51 ? 00:00:00 /usr/libexec/postfix/master
root 8 1 0 05:51 ? 00:00:00 /usr/sbin/rsyslogd
postfix 76 1 0 05:51 ? 00:00:00 pickup -l -t unix -u
postfix 77 1 0 05:51 ? 00:00:00 qmgr -l -t unix -u
postfix 78 1 0 05:51 ? 00:00:00 smtpd -n smtp -t inet -u -o
postfix 79 1 0 05:51 ? 00:00:00 proxymap -t unix -u
postfix 80 1 0 05:51 ? 00:00:00 tlsmgr -l -t unix -u
root 81 0 4 05:52 pts/0 00:00:00 bash
root 95 81 0 05:52 pts/0 00:00:00 ps -ef
設定変更した内容でコンテナを再作成し、docker stop
コマンドでコンテナを停止してみたところ、以下の通り、Exit 0
で正常に停止できていることがわかる。
# docker stop centos-postfix
centos-postfix
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4050d7cdc6d centos-postfix:1 "/startup.sh" 3 minutes ago Exited (0) 3 seconds ago centos-postfix
0 件のコメント:
コメントを投稿