通过主pipeclosuresDocker容器
我无法closures主pipe通过supervisorctl stop all
启动的Docker容器supervisorctl stop all
。 即使通过supervisorctl status
显示容器已closures, docker ps
和ps
表明它们实际上仍在运行。
咨询supervisorctl stop <name>
操作的主pipe文档显示,如果在某个宽限期之后仍然运行, SIGTERM
被发送到进程之后的SIGKILL
。 我试图手动做到这一点,发现
- 发送到
docker run
进程的SIGTERM
不会执行任何操作 -
SIGKILL
会杀死进程,但实际上并没有更新docker。docker ps
显示这个容器仍在运行 - 主pipe的
SIGKILL
不closures容器
问题是:如何正确closures一个Docker容器的主pipe?
以下是我的模拟pipe理员的实验结果:
开始位置: 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
接下来的主pipe会做的是发行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
在上面的实验中,主pipeclosures了(为了避免自动启动行为干扰)。 主pipe无法实现将SIGKILL
明确发送到stream程的结果; 该过程仍然存在(即使监督员以其他方式logging状态)。 docker stop <container_id>
不过停止了容器。
更新
Docker容器内部也是一个pipe理特定进程的supervisord
进程。 也许问题是信号不传播,因此它不会closures…
更新2
我缩小了这个问题。 我能够直接从Dockerfile
启动一个容器进程,而不是通过启动supervisord
,它Dockerfile
。 我可以通过主pipe(控制集装箱的docker集装箱以外的那个集装箱)来控制这个集装箱。
更新3
按照这里的build议设置stopasgroup=true
不会改变任何东西。
更新4
我能够解决其中一个问题: supervisorctl
不能closures进程。 问题是,我正在启动泊坞窗容器的监督员configuration文件与command=sudo docker run...
创build一个sudo docker run...
和docker run...
进程。 supervisorctl stop...
刚刚终止了sudo docker run...
进程,而实际的docker进程仍在运行。 当我省略sudo
命令时,每个超级用户程序只启动一个进程, supervisorctl stop
终止进程。
一个问题仍然是, docker ps
显示容器仍在运行,而ps aux
不运行。 奇怪的是,容器似乎仍然是积极的,因为他们回应请求。 快速看一下进程列表,确认docker容器产生的所有进程仍然是活动的,但进程列表中缺lessdocker run...
进程。
更新5
发送SIGTERM
, SIGHUP
或SIGQUIT
到docker run
进程似乎没有对进程做任何事情。 只有SIGKILL
才能正确终止docker进程。 主pipe得到正确更新,但docker ps
仍然显示docker进程运行。
我想我发现了这个问题。 我没有意识到,但是当docker集装箱启动时,有多种启动程序的方法。
显然, CMD myexec param1 param2
启动一个shell,然后启动myexec
(事实上,这两个进程在容器中可见/bin/sh -c myexec...
在PID 1.更好的方法是直接启动程序我的情况supervisord)。
另一方面, CMD ["/usr/bin/python", "/usr/local/bin/supervisord", "-c", "/root/supervisord.conf", "--nodaemon"]
工作正常。 我现在可以通过主pipe启动和停止docker集装箱。
以下是 Docker文档中的相关部分:
CMD指令有三种forms:
CMD ["executable","param1","param2"]
(execforms,这是首选forms)
CMD ["param1","param2"]
参数1CMD ["param1","param2"]
参数2CMD ["param1","param2"]
(作为默认参数ENTRYPOINT)
CMD command param1 param2
(shellforms)
更新
示例主pipe文件(在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(外部)主pipe文件的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