通过主管

时间:2015-07-03 02:56:43

标签: docker supervisord supervisor

我无法关闭主管通过supervisorctl stop all启动的Docker容器。即使supervisorctl status显示容器已关闭,docker psps也表明它们仍在运行。

咨询有关supervisorctl stop <name>操作的主管文档,显示SIGTERM如果在一段宽限期后仍然运行,则会发送到SIGKILL后的流程。我试图手动执行此操作并发现

    发送到SIGTERM进程的
  • docker run没有做任何事情
  • SIGKILL确实会杀死进程,但实际上并没有更新docker。 docker ps显示此容器仍在运行
  • 主管SIGKILL没有关闭容器

问题是:如何通过主管正确关闭Docker容器?

这是我模拟主管的实验结果:

起始位置:foo-1bar-1正在运行(我将GCE容器留在其中,以防它们产生影响)。 ps auxdocker 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流程发送SIGHUPSIGQUITdocker run似乎无法对流程执行任何操作。只有SIGKILL才能正确终止docker进程。主管正确更新,但docker ps仍然显示停靠进程正在运行。

1 个答案:

答案 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