你如何附加和分离 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退出。 关闭xtermkonsole 等是否有效?它对我有用(我变得超然)。 【参考方案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-PQ 不起作用,ctrl-C...最终我打开了另一个终端会话,我做了“docker stop containerid”和“docker start containerid”,它完成了工作.很奇怪。

【讨论】:

如果您使用--rm 标志启动容器,这将不起作用。如果您使用 -it 标志启动容器,Ctrl+PCtrl+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仓库的方法

Docker是啥?

Docker Compose Django、Webpack 和构建静态文件

Docker底座