1

コンテナー内で実行されているアプリケーションの場合、コンテナーが (正常に) シャットダウンされているときに SIGTERM を受け取ることが望ましいです。同時に、出力をログ ファイルに出力したいと考えています。

したがって、docker コンテナーの startscript では、execこれに似たbash を使用していました。

exec command someParam >> stdout.log

これは問題なく機能しcommand、コンテナーのルート プロセスであり、SIGTERM を受け取るシェルを置き換えました。

アプリケーションは多くのログを記録する傾向があるため、Apache のrotatelogsツールを使用してログ ローテーションを追加することにしました。

exec command | rotatelogs -n 10 stdout.log 10M

command残念ながら、パイプを使用することで、execはシェルを置き換えることができなくなったようです。実行中のコンテナー内のプロセスを で見るとpstree -p、次のようになります。

mycontainer@/#pstree -p
start.sh(1)-+-command(118)
            `-rotatelogs(119)

そのため、bash はルート プロセスのままであり、コマンドに SIGTERM を渡しません。exec に出くわす前に、シグナル ハンドラーを bash スクリプトにインストールする方法を見つけましcommandkill。ただし、これは非常に複雑になり、PID の取得も必ずしも簡単ではありませんでした。シグナル処理に関しては exec の利便性を維持し、ログ ローテーションのパイプを取得したいと考えています。これを達成する方法はありますか?

4

2 に答える 2

0

プロセス置換を使用することで、これを回避できました。あなたの特定のケースでは、以下がうまくいくかもしれません。

exec command > >(rotatelogs -n 10 stdout.log 10M)

シナリオを再現するために、この単純な Dockerfile を作成しました

FROM perl
SHELL ["/bin/bash", "-c"]

# The following will gracefully terminate upon docker stop
CMD exec perl -e '$SIG{TERM} = sub { $|++; print "Caught a sigterm!\n"; sleep(5); die "is the end!" }; sleep(30);' 2>&1 > >(tee /my_log)

# The following won't gracefully terminate upon docker stop
#CMD exec perl -e '$SIG{TERM} = sub { $|++; print "Caught a sigterm!\n"; sleep(5); die "is the end!" }; sleep(30);' 2>&1 | tee /my_log

建てるdocker build -f Dockerfile.meu -t test .

走るdocker run --name test --rm -ti test

やめろdocker stop test

出力:

Caught a sigterm!
is the end! at -e line 1.
于 2022-02-21T00:58:07.510 に答える