查阅supervisor文档中关于“supervisorctl stop ”操作的说明,发现会向进程发送“SIGTERM”,然后在一定的宽限期后再发送“SIGKILL”以终止进程。我尝试手动执行此操作,并发现:
- 发送到“docker run”进程的“SIGTERM”没有任何作用。 - “SIGKILL”确实可以杀死进程,但实际上并未更新docker。“docker ps”显示此容器仍在运行。 - Supervisor的“SIGKILL”无法关闭容器。
问题是:如何通过supervisor正确关闭Docker容器?
以下是模拟supervisor的实验结果:
起始状态:foo-1和bar-1正在运行(我将GCE容器保留了下来,以防它们有所不同)。 “ps aux”和“docker ps”是同步的。
me@devenv:~$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5ba70bf8937f me/app:foo "/bin/sh -c 'supervi 5 minutes ago Up 5 minutes foo-1
e1a684bcfceb me/app:bar "/bin/sh -c 'supervi 5 minutes ago Up 5 minutes bar-1
fce5db0517df google/cadvisor:0.8.0 "/usr/bin/cadvisor" 35 minutes ago Up 35 minutes bbbb
db677eed47ef kubernetes/pause:go "/pause" 35 minutes ago Up 35 minutes 0.0.0.0:4194->8080/tcp aaaa
me@devenv:~$ ps aux | grep "docker run"
root 23358 0.0 0.1 124092 11856 pts/0 Sl 02:05 0:00 docker run --rm --name foo-1 ... -i me/app:foo
root 23365 0.0 0.1 124092 11928 pts/0 Sl 02:05 0:00 docker run --rm --name bar-1 ... -i me/app:bar
通过向进程发送SIGTERM
信号来模拟supervisorctl stop foo-1
命令。结果:进程仍处于活动状态。
me@devenv:~$ sudo kill -SIGTERM 23358
... <waiting> ...
me@devenv:~$ ps aux | grep "docker run"
root 23358 0.0 0.1 124092 11856 pts/0 Sl 02:05 0:00 docker run --rm --name foo-1 ... -i me/app:foo
root 23365 0.0 0.1 124092 11928 pts/0 Sl 02:05 0:00 docker run --rm --name bar-1 ... -i me/app:bar
me@devenv:~$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5ba70bf8937f me/app:foo "/bin/sh -c 'supervi 6 minutes ago Up 6 minutes foo-1
e1a684bcfceb me/app:bar "/bin/sh -c 'supervi 6 minutes ago Up 6 minutes bar-1
fce5db0517df google/cadvisor:0.8.0 "/usr/bin/cadvisor" 36 minutes ago Up 36 minutes bbbb
db677eed47ef kubernetes/pause:go "/pause" 36 minutes ago Up 36 minutes 0.0.0.0:4194->8080/tcp aaaa
接下来主管会发出 SIGKILL
信号。结果:进程被杀死(ps aux
),但在 docker 进程中仍然显示为正在运行(docker ps
)。
me@devenv:~$ sudo kill -SIGKILL 23358
me@devenv:~$ ps aux | grep "docker run"
root 23365 0.0 0.1 124092 11928 pts/0 Sl 02:05 0:00 docker run --rm --name bar-1 ... -i me/app:bar
me@devenv:~$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5ba70bf8937f me/app:foo "/bin/sh -c 'supervi 19 minutes ago Up 19 minutes foo-1
e1a684bcfceb me/app:bar "/bin/sh -c 'supervi 19 minutes ago Up 19 minutes bar-1
fce5db0517df google/cadvisor:0.8.0 "/usr/bin/cadvisor" 49 minutes ago Up 49 minutes bbbb
db677eed47ef kubernetes/pause:go "/pause" 49 minutes ago Up 49 minutes 0.0.0.0:4194->8080/tcp aaaa
在上述实验过程中,为避免自启动行为干扰,监管进程已关闭。然而,即使监管程序记录显示相反的结果,Supervisor 发送
SIGKILL
信号给该进程也无法终止该进程;但是,通过使用 docker stop <container_id>
命令可以停止容器。
更新
在 Docker 容器内部还运行着一个管理某些进程的 supervisord
进程。或许问题在于信号未被传递,因此进程无法关机...
更新 2
我缩小了问题范围。我能够通过直接从 Dockerfile
中开始容器进程来控制此容器(而不是通过启动 supervisord
),这样做有所区别。我能够通过监管程序 (位于 Docker 容器之外,用于控制容器)来控制此容器。
更新 3
如此处建议,将 stopasgroup=true
设为 true 并没有改变什么。
更新 4
我已经解决了其中一个问题:监管程序无法关闭进程。问题在于,在监管配置文件中使用 command=sudo docker run...
启动 Docker 容器时,会创建一个 sudo docker run...
进程和一个 docker run...
进程。当运行 supervisorctl stop...
时,只会终止 sudo docker run...
进程,而实际的 Docker 进程仍在运行。当我省略 sudo
命令时,每个监管程序只会启动一个进程,并且可以通过 supervisorctl stop
命令终止该进程。
问题仍然存在,即 docker ps
显示容器仍在运行,但 ps aux
显示相反的结果。奇怪的是,容器仍然对请求做出响应。快速查看进程列表可以确认,由 Docker 容器生成的所有进程仍处于活动状态,但进程列表中缺少 docker run...
进程。
更新 5
向 docker run
进程发送 SIGTERM
、SIGHUP
或 SIGQUIT
信号似乎对该进程没有任何影响。只有使用 SIGKILL
才能正常终止 Docker 进程。监管程序会得到更新,但 docker ps
仍然显示 Docker 进程正在运行。
CMD ["executable"]
,但是supervisor仍然让我的容器保持运行状态。现在我担心我一开始就没有正确地运行容器。 - Daniel Buckmaster--rm
是关键。我会再试一次! - Daniel Buckmaster--rm
对于命名容器有帮助,否则在终止容器后,一个带有该名称的镜像仍会存在,这会阻止容器的后续运行(除非您手动删除该镜像)。 - orange