你如何附加和分离 Docker 的进程?
Posted
技术标签:
【中文标题】你如何附加和分离 Docker 的进程?【英文标题】:How do you attach and detach from Docker's process? 【发布时间】:2013-11-10 09:13:29 【问题描述】:我可以附加到 docker 进程,但 Ctrl+c 无法从中分离。 exit
基本上停止了这个过程。
让进程运行、偶尔附加到它以进行一些更改然后分离的推荐工作流程是什么?
【问题讨论】:
使用nsenter时,我只是Ctrl-D退出。 关闭xterm
、konsole
等是否有效?它对我有用(我变得超然)。
【参考方案1】:
如果 --sig-proxy=false 方法不起作用,那么您还可以使用以下方法更改转义序列:
docker attach --detach-keys="<sequence>" <container_name or id>
例如,我想使用“ctrl-c”分离容器,然后我可以使用以下方法附加容器:
docker attach --detach-keys="ctrl-c" <container_name or id>
的格式可以是字母 [a-Z],也可以是 ctrl- 与以下任意组合:
a-z(单个小写字母字符) @(在符号处) [(左括号) \(两个反斜杠) _(下划线) ^(插入符号)有关更多信息,另请参阅 -> Override the detach sequence
【讨论】:
【参考方案2】:我发现documentation 关于附加和分离有点复杂。
我尝试了不同的选项来启动一个容器并从另一个终端附加到它。下表总结了结果:
具有以下列含义:
-d
- 是否使用 docker run -d
选项
--sig-proxy
- 是 docker attach --sig-proxy=true|false
过去不使用的选项
--no-stdin
- 是 docker attach [--no-stdin]
过去不使用的选项
keys
- docker 是否将输入键发送到容器化应用程序
^C
- 当用户按下 Ctrl+C
时发生了什么
^P ^Q
- 当用户按下 Ctrl+P Ctrl+Q
时发生了什么
有几个发现:
附件行为不依赖于-d
选项,而是来自-i
和-t
您可以考虑将列附加到从另一个终端(例如docker attach --sig-proxy=false
,您可以更改连接选项)或从当前终端(但您不能更改连接选项;--sig-proxy=true
)到容器的连接
分离取决于运行选项,可以通过三种方式完成:
docker run [-i|-t]
并通过 docker attach --sig-proxy=false CONT
从另一个终端连接 -> 按 Ctrl+C
docker run -it
并通过 docker attach
从另一个终端连接 -> 按 Ctrl+P Ctrl+Q
docker run -it
并通过 docker attach --no-stdin
从另一个终端连接 -> 按 Ctrl+C
(当然,您应该为容器名称或图像等命令提供其他必要的参数)
附:我用-i
和-t
(只有其中一个)尝试了不同的场景,但没有得到行为上的差异。我看到@ken-cochrane 提供了以下内容:
docker run -i → 不能用 ^P^Q 分离;会破坏标准输入
但我没有成功复制这个。
【讨论】:
【参考方案3】:要从正在运行的容器中分离,请使用 ^P^Q(按住 Ctrl,按 P,按 Q kbd>,松开 Ctrl)。
有一个问题:这仅在容器以 -t
和-i
启动时才有效。
如果您有一个正在运行的容器在没有这些选项中的一个(或两个)的情况下启动,并且您使用docker attach
附加,则需要找到另一种分离方式。根据您选择的选项和正在运行的程序,^C 可能会起作用,也可能会杀死整个容器。您必须进行实验。
另一个问题:根据您使用的程序,您的终端、shell、SSH 客户端或多路复用器可能会拦截 ^P 或 ^ Q(通常是后者)。要测试这是否是问题所在,请尝试运行或附加 --detach-keys z
参数。您现在应该可以通过按 z 进行分离,无需任何修饰符。如果这有效,则另一个程序正在干扰。解决这个问题的最简单方法是使用--detach-keys
参数set your own detach sequence。 (例如,要使用 ^K 退出,请使用 --detach-keys 'ctrl-k'
。)或者,您可以尝试禁用终端或其他干扰程序中的密钥拦截。例如,stty start ''
或 stty start undef
可能会阻止终端在某些 POSIX 系统上拦截 ^Q,尽管我没有发现这有帮助。
【讨论】:
指定容器必须以-t
和-i
启动...谢谢!【参考方案4】:
更新
我通常使用 docker attach 来查看 STDOUT 显示的内容,以便对容器进行故障排除。我刚刚找到docker logs --follow 621a4334f97b
,它让我可以看到 STDOUT,同时还能在不影响容器操作的情况下按 ctrl+c 关闭它!正是我一直想要的。
...当然,您需要替换为您自己的容器 ID。
原答案
我想让容器继续运行,但在没有使用-it
启动容器的情况下连接。我的解决方案是牺牲我的 SSH 连接(因为我是通过 SSH 连接到运行容器的机器上)。终止该 ssh 会话使容器完好无损,但使我与它分离。
【讨论】:
【参考方案5】:要在不退出 shell 的情况下分离 tty,请使用转义序列 Ctrl+P 后跟 Ctrl+Q kbd>。更多详情here.
来自this source的其他信息:
docker run -t -i → 可以使用^P^Q
分离并使用 docker attach 重新附加
docker run -i → 不能用^P^Q
分离;会破坏标准输入
docker run → 不能用^P^Q
分离;可以 SIGKILL 客户端;可以使用 docker attach 重新附加
【讨论】:
如果它确实按照文档中的描述工作,这将是一个很好的答案。 我发现即使使用 -it 运行,如果您还使用清理标志 (--rm) 启动容器,分离序列也会失败。这对某些人来说可能很明显,但它比我想承认的更常让我感到痛苦。 另一种选择是关闭终端窗口或 cmd-w :) 您可以设置可配置的分离键,例如"detachKeys": "ctrl-a,a"
在你的 .docker/config.json 文件中或--detach-keys "ctrl-a,a"
在带有附加等的命令行中。
Ctrl + Z
不会分离;它只是该过程的背景。它与分离不同,会带来性能损失。【参考方案6】:
如果您只想对文件进行一些修改或检查进程,这可能是您想要的另一种解决方案。
您可以运行以下命令从现有容器中执行新进程:
sudo docker exec -ti [CONTAINER-ID] bash
会用bash shell启动一个新进程,你可以直接用Ctrl+C退出它,不会影响原来的进程。
【讨论】:
这个成功了,你可以在完成后输入“exit”而不影响原来的过程。 这是附加到正在运行的容器的好方法。但是如果(比如说)我在容器中运行了一些进程并且我想重新启动该进程怎么办?啊,我可以杀死旧进程,重新启动新进程,然后使用 C-p,C-q,因为它是交互式 tty,所以它可以工作。我也喜欢 --sig-proxy=false 方法,但它更通用,不会强制中断当前进程。 “attach”跟Docker有特定的含义,exec
不是。【参考方案7】:
对于遇到与我相同的问题的任何人(即使在设置分离键的情况下也无法在不杀死容器的情况下分离)......
使用docker-compose up -d
启动容器时
而不是使用docker attach container name
查看拖尾日志....
try docker-compose logs -f service name
ctrl-c 杀死日志尾部而不杀死你的容器
service name
是 docker-compose.yml 文件中列出的服务。(例如,当容器名称=elk_logstash_1 -> 服务名称=logstash
HTH
【讨论】:
【参考方案8】:如果你只需要 docker 进程进入后台你可以使用
Ctrl + Z
请注意,这不是真正的分离,它会带来性能损失。
(您可以使用bg
命令将其返回到前台)。
如果您不再需要它,另一种选择是关闭您的终端。
【讨论】:
【参考方案9】:我遇到了同样的问题,ctrl-P 和 Q 不起作用,ctrl-C...最终我打开了另一个终端会话,我做了“docker stop containerid”和“docker start containerid”,它完成了工作.很奇怪。
【讨论】:
如果您使用--rm
标志启动容器,这将不起作用。如果您使用 -it
标志启动容器,Ctrl+P
和 Ctrl+Q
可以工作。【参考方案10】:
在同一个 shell 中,按住 ctrl 键并按 p 然后按 q
【讨论】:
这仅在您使用-it
标志启动容器时有效。【参考方案11】:
要停止 docker 进程并释放端口,首先使用 ctrl-c 退出容器,然后使用 docker ps 查找正在运行的容器列表。然后,您可以使用 docker container stop 停止该进程并释放其端口。您可以从 docker ps 命令中找到容器名称,该命令在名称列中给出名称。希望这能解决您的疑问....
【讨论】:
【参考方案12】:也请查看the --sig-proxy
option:
docker attach --sig-proxy=false 304f5db405ec
然后用CTRL+c分离
【讨论】:
要尝试从 run 而不是 attach 开始,我尝试了:docker run -ti --sig-proxy=false busybox top
这似乎不起作用,进程被 ctrl-c 杀死,但从 docker run -t -sig-proxy=false busybox top
开始似乎可以工作并启用退出使用 ctrl-c
Ctrl-c
也会停止容器。
这是此处列出的解决方案中唯一适用于运行 Docker 19.03.5 的 Debian 9 服务器的解决方案。问题是,为什么这不是附加命令的默认设置?这似乎是最常见的用例。
Ctrl-p、Ctrl-q 序列对我不起作用(从 docker container attach xyz 开始).. 但这确实有效。谢谢@czerasz【参考方案13】:
-
打开一个新终端
找到正在运行的容器Id
docker ps
杀死容器docker kill $containerId
【讨论】:
【参考方案14】:我在 Mac 上,出于某种原因,Ctrl-p Ctrl-q 会仅当我还持有 Shift
时才有效【讨论】:
【参考方案15】:要从容器中分离,您只需按住 Ctrl 并按 P + Q。
要附加到您使用的正在运行的容器:
$ docker container attach "container_name"
【讨论】:
【参考方案16】:当其他方法都不起作用时,打开一个新的终端然后:
$ ps aux | grep attach
username <pid_here> .............. 0:00 docker attach <CONTAINER_HASH_HERE>
username <another_pid> .............. 0:00 grep --color=auto attach
$ kill -9 <pid_here>
【讨论】:
真是个陷阱!谢谢,这是唯一有效的方法。-9
不是必需的。
这也会杀死容器——可能取决于设置了哪些标志。
请注意如果显示了两个 pid,那么第一个是父进程。您应该使用第二个 pid 杀死 docker attach
而不是它的父级。【参考方案17】:
我觉得这要视情况而定。以下面的容器为例:
# docker run -it -d ubuntu
91262536f7c9a3060641448120bda7af5ca812b0beb8f3c9fe72811a61db07fc
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
91262536f7c9 ubuntu "/bin/bash" 5 seconds ago Up 4 seconds serene_goldstine
(1) 使用“docker attach
”附加容器:
由于“docker attach
”不会分配新的tty,而是重用原来正在运行的tty,所以如果你运行exit
命令,会导致正在运行的容器退出:
# docker attach 91262536f7c9
exit
exit
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
91262536f7c9 ubuntu "/bin/bash" 39 minutes ago Exited (0) 3 seconds ago serene_goldstine
所以除非你真的想让正在运行的容器退出,你应该使用 Ctrl+p + Ctrl+q kbd>。
(2) 使用“docker exec
”
由于“docker exec
”将分配一个新的tty,所以我认为你应该使用exit
而不是Ctrl+p + Ctrl+q。
下面是执行Ctrl+p + Ctrl+q退出容器:
# docker exec -it 91262536f7c9 bash
root@91262536f7c9:/# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 18160 1908 ? Ss+ 04:03 0:00 /bin/bash
root 15 0.0 0.0 18164 1892 ? Ss 04:03 0:00 bash
root 28 0.0 0.0 15564 1148 ? R+ 04:03 0:00 ps -aux
root@91262536f7c9:/# echo $$
15
然后再次登录容器,你会看到前面docker exec
命令中的bash
进程仍然存在(PID为15):
# docker exec -it 91262536f7c9 bash
root@91262536f7c9:/# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 18160 1908 ? Ss+ 04:03 0:00 /bin/bash
root 15 0.0 0.0 18164 1892 ? Ss+ 04:03 0:00 bash
root 29 0.0 0.0 18164 1888 ? Ss 04:04 0:00 bash
root 42 0.0 0.0 15564 1148 ? R+ 04:04 0:00 ps -aux
root@91262536f7c9:/# echo $$
29
【讨论】:
以上是关于你如何附加和分离 Docker 的进程?的主要内容,如果未能解决你的问题,请参考以下文章
docker-compose 用于将 VS Code 中的 node.js 调试器附加到 WSL docker 中的节点进程
docke镜像上传到dockerhub仓库和阿里云docker仓库的方法