我无法关闭主管通过supervisorctl stop all
启动的Docker容器。即使supervisorctl status
显示容器已关闭,docker ps
和ps
也表明它们仍在运行。
咨询有关supervisorctl stop <name>
操作的主管文档,显示SIGTERM
如果在一段宽限期后仍然运行,则会发送到SIGKILL
后的流程。我试图手动执行此操作并发现
SIGTERM
进程的docker run
没有做任何事情SIGKILL
确实会杀死进程,但实际上并没有更新docker。 docker ps
显示此容器仍在运行SIGKILL
没有关闭容器问题是:如何通过主管正确关闭Docker容器?
这是我模拟主管的实验结果:
起始位置: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
通过向流程发送supervisorctl stop foo-1
来模拟SIGTERM
。结果:流程仍然有效。
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
在上述实验期间,主管被关闭(以避免其自动启动行为干扰)。主管无法实现将SIGKILL
明确发送到流程的结果;该过程仍然存在(即使主管记录否则)。
然而,docker stop <container_id>
确实阻止了容器。
更新
Docker容器内部还运行一个supervisord
进程来管理某些进程。也许问题是信号没有传播,因此它不会被关闭......
更新2
我缩小了问题范围。我能够从Dockerfile
直接启动容器流程,而不是通过启动supervisord
,这会产生影响。我可以通过主管(控制容器的docker容器之外的那个)来控制这个容器。
更新3
按照建议here设置stopasgroup=true
对我来说不会改变任何内容。
更新4
我能够解决其中一个问题:supervisorctl
无法关闭进程。问题是我在使用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
向SIGTERM
流程发送SIGHUP
,SIGQUIT
或docker run
似乎无法对流程执行任何操作。只有SIGKILL
才能正确终止docker进程。主管正确更新,但docker ps
仍然显示停靠进程正在运行。
答案 0 :(得分:7)
我想我发现了这个问题。我没有意识到这一点,但是当一个docker容器被启动时,有多种方法可以启动程序。
显然CMD myexec param1 param2
启动一个shell,然后启动myexec
(实际上这两个进程在PID 1中的/bin/sh -c myexec...
容器中可见。更好的方法是启动程序直接(在我的情况下是supervisord)。
另一方面,CMD ["/usr/bin/python", "/usr/local/bin/supervisord", "-c", "/root/supervisord.conf", "--nodaemon"]
工作正常。我现在能够通过主管启动和停止docker容器。
Here's docker docs中的相关部分:
CMD指令有三种形式:
CMD ["executable","param1","param2"]
(执行形式,这是首选形式)
CMD ["param1","param2"]
(作为ENTRYPOINT的默认参数)
CMD command param1 param2
(贝壳形式)
<强>更新强>
示例管理程序文件(在Docker容器内):
[program:app]
command=python run_web_server.py
stdout_logfile=/var/log/app/app.log
directory=/opt/app
autostart=true
autorestart=false
stopsignal=INT
redirect_stderr=true
startretries=0
stopasgroup=true
killasgroup=true
[unix_http_server]
file=/var/run/supervisor.sock
chmod=0700
[supervisord]
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid
childlogdir=/var/log/supervisor
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock
用于生成Docker(外部)管理员文件的mako模板:
[program:container]
command=docker run --rm --name ${name} \
% if container_links is not UNDEFINED:
% for host in container_hosts:
--add-host ${host['name']}:${host['ip']} \
% endfor
% endif
% if container_links is not UNDEFINED:
% for link in container_links:
--link ${link}:${link} \
% endfor
% endif
% if port_mappings is not UNDEFINED:
% for ext in port_mappings:
-p ${ext}:${port_mappings[ext]} \
% endfor
% endif
-e "INSTANCE_NAME=${name}" \
-e "TZ=${timezone}" \
% if environ is not UNDEFINED:
% for k in environ:
-e "${k}=${environ[k]}" \
% endfor
% endif
-v ${deployment_dir}/tmp:${deployment_dir}/app/tmp \
... more -v
-i foo/app-${version}:${type}
stdout_logfile=${deployment_dir}/log/${name}.log
redirect_stderr=true
autostart=false
autorestart=false
% if priority is not UNDEFINED:
priority=${priority}
% endif
startretries=0
# stopasgroup=true
# killasgroup=true