2016-09-28 7 views
13

はバックグラウンドでsleep 60を実行して終了以下、考えてみましょう:DockerコンテナのPID1が終了すると、他のプロセスはどうなりますか?

$ cat run.sh 
sleep 60& 
ps 
echo Goodbye!!! 
$ docker run --rm -v $(pwd)/run.sh:/run.sh ubuntu:16.04 bash /run.sh 
    PID TTY   TIME CMD 
    1 ?  00:00:00 bash 
    5 ?  00:00:00 sleep 
    6 ?  00:00:00 ps 
Goodbye!!! 

をこれがPID1としてbashと、ドッカーコンテナを開始します。その後、sleepプロセスをfork/execした後、bashを終了します。 Dockerコンテナが死ぬと、sleepプロセスが何とか死んでしまいます。

私の質問は:sleepプロセスが殺される仕組みは何ですか?私は子プロセスでSIGTERMを捕まえようとしましたが、それはつまらないようです。私の前提は、コンテナが使用しているcgroupをシャットダウンするときに何か(DockerまたはLinuxカーネルのいずれか)がSIGKILLを送信していることです。しかし、これを明確にする文書はどこにも見つかりませんでした。あなたのinitプロセスは、あなたのアプリケーションであれば、それはおそらく唯一の、それ自身ではなく、すべてのシャットダウンします、

EDIT私が説明に来て最も近い次baseimage-dockerからの引用です容器内の他のプロセス。カーネルは強制的に他のプロセスを強制終了し、正常にシャットダウンする機会を与えず、ファイルの破損や古い一時ファイルなどを潜在的に破棄します。本当にすべてのプロセスを正常にシャットダウンする必要があります。

したがって、少なくともコンテナが終了すると、カーネルは残りのすべてのプロセスにSIGKILLを送信することを意味します。しかし、私はそれをどうするかを明確にしたい(つまり、cgroupsの機能ですか?)、理想的にはもっと権威のあるソースがいいと思います。

答えて

2

私はこれが実際にLinuxカーネルが終了しているという確かな証拠を思いついたようです。

(Linuxの2.6.24以降)CLONE_NEWPID

CLONE_NEWPIDフラグを使用して作成さ 新しい名前空間(すなわち、プロセスで作成された最初のプロセス:clone(2) manページでは、この便利なセクションがあります)はPID 1を持ち、ネームスペースの "init"プロセスは です。名前空間内で孤児になっている子 は、 init(8)ではなく、このプロセスに親子関係になります。従来のinitプロセスとは異なり、 のPID名前空間の "init"プロセスは終了することができ、終了した場合、 のすべてのプロセスが終了します。

残念ながら、名前空間内のプロセスがどのくらい正確に終了しているかはまだ分かりませんが、通常のプロセス終了とは異なり、プロセステーブルにエントリが残っていない可能性があります。ケースが何であれ、それは思わ明らかその:

  • カーネル自体がそれを作る、彼らは彼らにクリーンアップを行うためのあらゆる機会を可能にする方法で殺害されていない他のプロセス
  • を殺している(ほとんど?)SIGKILL
  • と同じ
+0

https://github.com/opencontainers/runc/blob/c4e0d94efacd6f6fb353a538cc01d10792cc3a35(あなたが[ホストのPID名前空間で実行されている]されている場合ドッカーズ 'runc'はクリーンアップを行うことが可能です/libcontainer/state_linux.go#L41-L45)。 – Matt

+0

カーネルはプロセスを終了させるために 'SIGKILL'を送ります。 – Matt

+0

@Mattお役立ち情報これらのプロセスをホストする 'init'プロセスの責任となるのでしょうか、それともカーネルがプロセステーブル自体からそれらを削除するのでしょうか? –

関連する問題