docker-compose down が遅い
TL;DR
CMD ["command", "param1", "param2"]
の形式で記述する
exec
コマンドを使う
Dockerコンテナの終了が遅い
docker-compose down
やdocker stop
したときに、Dockerコンテナの終了が遅いことがあります。
(数秒の時間がかかることがあります。)
しかも、docker-compose ps
で確認してみると、xxxxx exited with code 137
となっており、SIGKILLにより終了しています。
docker-compose down
が遅いと、作業にも支障がでますので、原因と解決策を調べてみました。
原因
docker stop
では、PID=1 のプロセスに対して SIGTERM
が送信されます。
このことが主な原因となっています。
Dockerfileに記述するCMD
は、コンテナ起動時に実行するコマンドを指定することができます。
この指定方法はいくつかありますが、
CMD ["command", "param1", "param2"]
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