2016-09-28 125 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!!! 

這將啓動一個泊塢的容器中,作爲bash PID1。然後它叉/執行一個sleep進程,然後bash退出。當Docker容器死亡時,sleep進程也死機。

我的問題是:什麼是sleep進程被殺死的機制?我試圖在子進程中捕獲SIGTERM,並且看起來沒有被絆倒。我的推測是,關閉容器正在使用的cgroup時,Docker或Linux內核正在發送SIGKILL,但我在任何地方都沒有找到說明這一點的文檔。

編輯我來解釋最接近的是從baseimage-docker以下報價:

如果你的init進程是你的應用程序,那麼它很可能只是關閉本身,而不是所有的容器中的其他進程。內核然後會強行終止其他進程,而不是讓他們有機會正常關閉,可能導致文件損壞,臨時文件過時等。您真的想要優雅地關閉所有進程。

因此,至少根據這一點,暗示當容器退出時,內核將發送一個SIGKILL到所有剩餘的進程。但是我還是希望清楚它是如何決定這麼做的(即它是cgroups的一個特徵嗎?),理想情況下更權威的來源會更好。

回答

2

好的,我似乎已經提出了一些更確鑿的證據,實際上,這是Linux內核做終止。在clone(2)手冊頁,有這個有用的部分:

CLONE_NEWPID(因爲Linux 2.6.24)

在一個新的命名空間(第一個創建的過程,即,使用CLONE_NEWPID標誌 創建的過程)具有PID 1,並且是命名空間的「init」進程 。在命名空間內成爲孤兒 的孩子將被重新設置爲此過程而不是 init(8)。與傳統的init進程不同,PID命名空間的「init」進程可以終止,如果是,則所有進程 中的命名空間終止。

不幸的是,對於名稱空間中的進程究竟如何終止仍然模糊不清,但也許這是因爲,與正常進程退出不同,進程表中沒有任何條目。無論是哪種情況,它似乎很清楚:

  • 內核自身殺死其他進程
  • 他們不是在一個方式,讓他們任何機會做清理喪生,使得它(幾乎?)等同於SIGKILL
+0

這是可能的碼頭工人'runc'做清理,如果你[在主機PID命名空間運行(https://github.com/opencontainers/runc/blob/c4e0d94efacd6f6fb353a538cc01d10792cc3a35 /libcontainer/state_linux.go#L41-L45)。 – Matt

+0

,內核確實發送了一個'SIGKILL'來終止進程。 – Matt

+0

@Matt很高興知道。它是否成爲主機'init'進程收穫這些進程的責任,還是內核將它們從進程表本身中刪除? –

相關問題