深入探究docker attach的退出方式
docker attach可以将当前终端的标准输入、标准输出和标准错误连接到指定的容器中,可以显示容器 ENTRYPOINT/CMD 进程的输出,是容器调试的重要方法。docker attach之后退出的方法,主要有CTRL-c和CTRL-p CTRL-q两种。大部分说法中,认为CTRL-c会导致容器退出,推荐使用CTRL-p CTRL-q方法。我在实际使用中,发现这些说法并不准确,这两种方法都会收到docker run和docker attach命令选项的影响。
1. CTRL-c方式
与普通的进程一样,docker attach之后执行CTRL-c会发送SIGINT信号。
docker attach命令有--sig-proxy选项,man docker attach中对该选项描述如下:
--sig-proxy=true|false Proxy all received signals to the process (non-TTY mode only). SIGCHLD, SIGKILL, and SIGSTOP are not proxied. The default is true.
可以看到,该选项仅在non-TTY模式下起作用,即docker run时不指定-t选项。此时,默认--sig-proxy为true,SIGINT信号被发送至docker中PID为1的进程。
doujl@ubuntu:~$ docker run -id centos:7 /bin/bash edfe9bc8ae02567ff9309ffb6940a9772f02a18d24e4cf04a9da8c84c01e1f52 doujl@ubuntu:~$ docker attach edfe ^C^C^C
doujl@ubuntu:~$ docker run -d centos:7 top -b 8700417c309d1b6c8e3a1618f38b232e8eddedae20287e73f2022b0cac716248 doujl@ubuntu:~$ docker attach 8700 top - 02:37:24 up 19 days, 1:59, 0 users, load average: 0.94, 1.03, 1.17 Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie %Cpu(s): 10.4 us, 2.0 sy, 0.0 ni, 87.2 id, 0.3 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 8066788 total, 752956 free, 3659576 used, 3654256 buff/cache KiB Swap: 8282108 total, 7576840 free, 705268 used. 3378516 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 51780 3576 3132 R 0.0 0.0 0:00.04 top^C doujl@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8700417c309d centos:7 "top -b" 11 seconds ago Exited (0) 3 seconds ago pensive_brahmagupta
上面两个例子中,docker run没有-t选项,docker attach中--sig-proxy默认为true,将信号发送至容器(SIGCHLD,SIGKILL,SIGSTOP除外)。因此SIGINT发送至PID为1的进程,分别为/bin/bash和top -b。第一个例子,/bin/bash没有处理SIGINT信号(加上-i是为防止进程退出)。第二个例子中,top -b响应了SIGINT信号并退出,因此容器退出。
如果在docker attach时设置--sig-proxy=false,SIGINT信号不会发送到容器中PID为1的进程,而是被docker attach进程响应
doujl@ubuntu:~$ docker run -id centos:7 /bin/bash 5a6d97406a068b1a58b02d4b3267a974b8c69e268d37db19b44b2858b5086e0f doujl@ubuntu:~$ docker attach --sig-proxy=false 5a6d ^C doujl@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5a6d97406a06 centos:7 "/bin/bash" 11 seconds ago Up 9 seconds reverent_goldstine
doujl@ubuntu:~$ docker run -d centos:7 top -b 37a80db8bf8f8c79bbb910353d04a46697ad54c0bcb4f34f4ef8edd42163d152 doujl@ubuntu:~$ docker attach --sig-proxy=false 37a8 top - 02:42:45 up 19 days, 2:04, 0 users, load average: 0.58, 0.74, 0.99 Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie %Cpu(s): 8.2 us, 1.7 sy, 0.0 ni, 90.1 id, 0.1 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 8066788 total, 782360 free, 3642612 used, 3641816 buff/cache KiB Swap: 8282108 total, 7576848 free, 705260 used. 3405820 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 51780 3668 3224 R 0.0 0.0 0:00.06 top^C doujl@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 37a80db8bf8f centos:7 "top -b" 15 seconds ago Up 13 seconds tender_kirch
上面两个例子中,CTRL-c都能退出,但退出的是docker attach进程,容器本身不受影响。
以上的例子中,docker run都没有-t选项,如果指定了-t选项呢?
doujl@ubuntu:~$ docker run -itd centos:7 /bin/bash 4ff1e8d42537115f46c98eeae6c1554b388cd3322039f8185bb4e3a1848ec519 doujl@ubuntu:~$ docker attach 4ff1 [root@4ff1e8d42537 /]# ^C [root@4ff1e8d42537 /]# ^C [root@4ff1e8d42537 /]#
doujl@ubuntu:~$ docker run -td centos:7 /bin/bash 7a8f3c2ba41b5b4c047dfe4b9d41774cb6972e1e969b38636affd39920b83b2f doujl@ubuntu:~$ docker attach 7a8f [root@7a8f3c2ba41b /]# ^C doujl@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7a8f3c2ba41b centos:7 "/bin/bash" 18 seconds ago Up 17 seconds peaceful_bose
doujl@ubuntu:~$ docker run -itd centos:7 top -b 829a0f9c9ac70147783d3db9674def5c2179059956923a1d59ccd8a33f339b37 doujl@ubuntu:~$ docker attach 829a top - 02:49:10 up 19 days, 2:10, 0 users, load average: 0.55, 0.72, 0.91 Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie %Cpu(s): 11.5 us, 2.3 sy, 0.0 ni, 86.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 8066788 total, 757280 free, 3659324 used, 3650184 buff/cache KiB Swap: 8282108 total, 7576884 free, 705224 used. 3384468 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 51780 3584 3140 R 0.0 0.0 0:00.05 top top - 02:49:10 up 19 days, 2:10, 0 users, load average: 0.55, 0.72, 0.91 Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 8066788 total, 757280 free, 3659324 used, 3650184 buff/cache KiB Swap: 8282108 total, 7576884 free, 705224 used. 3384468 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 51780 3584 3140 R 0.0 0.0 0:00.05 top^C doujl@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 829a0f9c9ac7 centos:7 "top -b" 12 seconds ago Exited (0) 2 seconds ago angry_yonath
doujl@ubuntu:~$ docker run -td centos:7 top -b 79cfe842cfba1b211dea37fafbc5676c9da2ad6e186f261cccee4098ee1dd02a doujl@ubuntu:~$ docker attach 79cf top - 02:50:02 up 19 days, 2:11, 0 users, load average: 0.33, 0.63, 0.87 Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie %Cpu(s): 10.3 us, 2.8 sy, 0.0 ni, 86.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 8066788 total, 749208 free, 3659560 used, 3658020 buff/cache KiB Swap: 8282108 total, 7576884 free, 705224 used. 3376832 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 51780 3636 3192 R 0.0 0.0 0:00.05 top top - 02:50:02 up 19 days, 2:11, 0 users, load average: 0.33, 0.63, 0.87 Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 8066788 total, 749208 free, 3659560 used, 3658020 buff/cache KiB Swap: 8282108 total, 7576884 free, 705224 used. 3376832 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 51780 3636 3192 R 0.0 0.0 0:00.05 top^C doujl@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 79cfe842cfba centos:7 "top -b" 9 seconds ago Up 7 seconds loving_ride
可以看到,docker run指定-t选项时,是否指定-i选项也会对docker attach命令有影响。指定-i选项时,SIGINT信号发送到了容器中PID为1的进程,不指定时,信号被docker attach接收。注意,此时docker attach的--sig-proxy选项不起作用。
综上,docker attach后执行CTRL-c会发送SIGINT信号,而信号的接收方会受到docker run的-i、-t选项,和docker attach的--sig-proxy选项影响。
2. CTRL-p CTRL-q方式
CTRL-p CTRL-q方式比较简单,只需要注意docker run时要同时指定-it选项。该方式只会退出docker attach,对容器没有影响
doujl@ubuntu:~$ docker run -itd centos:7 /bin/bash e73e04370cee90497783a621fd4a044ca196dc419c06a01bae5a4b116d7afc4e doujl@ubuntu:~$ docker attach e73e
#执行CTRL-p CTRL-q [root@e73e04370cee /]# doujl@ubuntu:~$ doujl@ubuntu:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e73e04370cee centos:7 "/bin/bash" 44 seconds ago Up 42 seconds vibrant_archimedes
如果-it选项没有同时指定,CTRL-p CTRL-q无法生效
3. 其他退出方式
上面两种方式在退出时都有限制,有没有其他方法呢?
其实,我们只要另起一个终端,把docker attach进程杀死就可以了
#终端1中执行,没有同时指定-it,CTRL-p CTRL-q无法退出
doujl@ubuntu:~$ docker run -id centos:7 /bin/bash
00c031965cb2075643e15a3b88141026e753a79e8b03b960880d505950488014
doujl@ubuntu:~$ docker attach 00c0 ^P /bin/bash: line 1: $'\020': command not found ^P
#终端2中杀死docker attach进程
doujl@ubuntu:~/dettach$ pkill -9 -f 'docker.*attach' doujl@ubuntu:~/dettach$
#终端1中,docker attach已退出 /bin/bash: line 2: $'\020': command not found 已杀死 doujl@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 00c031965cb2 centos:7 "/bin/bash" About a minute ago Up About a minute trusting_meitner
参考文档:
1. man docker attach
2. https://docs.docker.com/engine/reference/commandline/attach/
3. https://stackoverflow.com/questions/25267372/correct-way-to-detach-from-a-container-without-stopping-it/45985809#45985809