docker-compose down が遅い

f:id:utouto97:20210706233740j:plain

TL;DR CMD ["command", "param1", "param2"]の形式で記述する
execコマンドを使う

Dockerコンテナの終了が遅い

docker-compose downdocker stopしたときに、Dockerコンテナの終了が遅いことがあります。
(数秒の時間がかかることがあります。)
しかも、docker-compose ps で確認してみると、xxxxx exited with code 137となっており、SIGKILLにより終了しています。
docker-compose down が遅いと、作業にも支障がでますので、原因と解決策を調べてみました。

原因

docker stopでは、PID=1 のプロセスに対して SIGTERMが送信されます。
このことが主な原因となっています。

Dockerfileに記述するCMDは、コンテナ起動時に実行するコマンドを指定することができます。
この指定方法はいくつかありますが、

  1. CMD ["command", "param1", "param2"]
  2. CMD "command param1 param2"

のどちらかが多いのではないでしょうか。

このうち前者のCMD ["command", "param1", "param2"]は、execにより実行されています。
execコマンドでは、新規プロセスを生成して処理するのではなく、今のプロセスで処理します。
そのため、実行元のPIDを保持したまま処理が行われます。
CMD ["command", "param1", "param2"]の記述では、このexecコマンドによって実行されていることにより、PID=1として実行されていて、PID=1に対するSIGTERMを受け取ることができます。

一方で、後者のCMD "command param1 param2"は、sh -cにより実行されます。
sh -cで実行する場合は、新規プロセスが生成され、そのプロセスで実行されるため、PIDも実行元とは異なります。
そうなると、PID=1に対してSIGTERMが送られても、CMD "command param1 param2"により実行されているプロセスにはSIGTERMが送られません。

つまり、docker stopではPID=1のプロセスに対して、SIGTERMが送信されることが重要となっていて、それを踏まえてDockerfileやエントリーポイントを指定することで解決することができます。

解決策

原因はdocker stopではPID=1のプロセスに対して、SIGTERMが送信されるが、異なるPIDで実行してしまっていることでした。

そのため、解決するにはPID=1で実行すればよいということになります。

そこで、DockerfileにCMDを記述するときは、配列形式で記述するとよいです。

`CMD ["command", "param1", "param2"]`

また、エントリーポイントを指定していて、その中で複数コマンドを実行している場合もあると思います。
その場合は、コマンドの実行にexecコマンドを使うことで、PID=1として実行することができ、docker stopによって送信されるSIGTERMによる終了ができるようになります。

まとめ

CMD ["command", "param1", "param2"]の形式で記述する
execコマンドを使う

参考
docker stop | Docker Documentation
Dockerfile reference | Docker Documentation