【问题标题】:Correct way to detach from a container without stopping it在不停止容器的情况下从容器中分离的正确方法
【发布时间】:2014-10-05 16:53:25
【问题描述】:

在 Docker 1.1.2(最新)中,在不停止容器的情况下从容器分离的正确方法是什么?

例如,如果我尝试:

  • docker run -i -t foo /bin/bash
  • docker attach foo(用于已经运行的容器)

这两个都让我到达容器中的终端,我如何在不停止的情况下退出容器的终端?

exitCTR+C 都停止容器。

【问题讨论】:

  • “容器”只是进程可以在其中运行的一组受限命名空间(进程命名空间、文件系统命名空间等)。如果命名空间内没有进程,那么该命名空间是否真的存在?存在?它不像一个有内核响应时钟中断的虚拟机。无论如何。

标签: docker


【解决方案1】:

更新:如下回答中提到的Ctrl+pCtrl+q kbd> 现在会将交互模式转换为守护进程模式。


Ctrl+C(或 Ctrl+\)应该将您与容器分离,但 它会杀死容器,因为你的主进程是一个 bash。

关于 docker 的小课。 容器不是真正的全功能操作系统。当您运行容器时,您启动的进程将采用 PID 1 并承担 init 电源。因此,当该进程终止时,守护进程会停止容器,直到启动新进程(通过 docker start)(关于此事的更多解释http://phusion.github.io/baseimage-docker/#intro

如果你想要一个始终以分离模式运行的容器,我建议你使用

docker run -d foo

容器上有一个 ssh 服务器。 (最简单的方法是按照dockerizing openssh 教程https://docs.docker.com/engine/examples/running_ssh_service/

或者你可以通过

重新启动你的容器
docker start foo

(默认是分离的)

【讨论】:

  • +1 用于 baseimage-docker。很高兴知道有一个模板包含有关 Docker 困难部分的建议。
  • 请注意,ssh 并不是绝对必要的:blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker
  • 运行包含在 -d 模式下非常有帮助。此外,通过 Dockerfile 启动 ssh 的链接让我的生活变得轻松。
  • 分离 使用 Ctrl-p、Ctrl-q。这个答案的建议会杀死一个容器。
  • 这对我有用(取自下面的答案):从 -ti -d 开始,然后使用 docker attach 附加,然后使用 first ctrl+p 和然后 ctrl+q。我想,我可以只使用其中一个键盘快捷键。
【解决方案2】:

键入 Ctrl+p,然后键入 Ctrl+q。它将帮助您将交互模式转换为守护模式。

https://docs.docker.com/engine/reference/commandline/cli/#default-key-sequence-to-detach-from-containers:

一旦附加到容器上,用户就会从容器中分离出来,并使用 CTRL-p CTRL-q 键序列使其继续运行。此分离键序列可使用detachKeys 属性进行自定义。 [...]

【讨论】:

  • 它似乎不适用于(试图退出附加的 Wekan 容器)。
  • 我已经访问过这个页面很多次了,因为我记不起这个组合键了! :-D
  • @danger89 ctrl-p, ctrl-q 仅在您以交互模式 (-it) 启动容器时起作用。如果您以守护程序模式 (-d) 启动它并附加到它,您可以退出它,它仍将在后台运行。
  • @SlimShady 按 Ctrl + P 然后按 Ctrl + Q 退出,不是其中一个,而是两个都按这个顺序。
【解决方案3】:

我认为 Ashwin 的答案是最正确的,我的旧答案如下。


我想在这里添加另一个选项,即按如下方式运行容器
docker run -dti foo bash

然后您可以进入容器并使用 bash 运行

docker exec -ti ID_of_foo bash

无需安装 sshd :)

【讨论】:

  • 我认为在第二个命令中您需要将 foo 替换为 foo 的容器 id
  • 在这种情况下,我认为docker attach 会更标准,通过重新附加到第一次 bash 运行。 docker exec 也可以在这里工作,但是除了第一个之外,它还创建了一个新的 bash 进程。当然,该进程是在第一个进程的相同上下文/环境/容器中创建的,但它是不同的(类比是在您最喜欢的终端模拟器中打开一个新的终端选项卡)。
  • 这是唯一适用于我的特定场景的命令。使用 VS Code 在 Docker 中运行测试套件。在我的情况下,它是一个 Rails 应用程序,所以要启动后台容器 docker-compose run -d --name app_tests app spring server,然后我可以通过将 vscode 测试命令设置为 docker exec -ti app_tests spring rspec 来运行测试
【解决方案4】:

如果您执行“docker attach”container id”,您将进入容器。 要在不停止容器的情况下退出容器,您需要输入 Ctrl+P+Q

【讨论】:

  • 优于 Ctrl+P 和 Ctrl+Q
  • Ctrl+P, Q(仍然按住Ctrl) ;)
  • 它返回给我:Error response from daemon: Container f560a0ad6806150b2775d0b6e6d5f7065a03775bae858fb4fb7df05a277976db is not running
【解决方案5】:

从交互式容器中分离的默认方式是 Ctrl+P Ctrl+Q,但是你可以在运行新容器或使用 the --detach-keys flag 附加到现有容器时覆盖它。

【讨论】:

    【解决方案6】:

    尝试 CTRL+P,CTRL+Q 将交互模式转为守护进程。

    如果这不起作用并且您通过docker attach 附加,您可以通过杀死docker attach 进程来分离。

    更好的方法是使用 sig-proxy 参数来避免将 CTRL+C 传递给您的容器:

    docker attach --sig-proxy=false [container-name]
    

    docker run 命令也可以使用相同的选项。

    【讨论】:

    • 虽然 --sig-proxy=false 非常有用,但它不适用于未指定的已附加容器。问题是,在附加之后似乎没有办法在不终止进程的情况下进行分离,包括“终止 docker attach 进程”。 C-p,C-q 不适用于附加容器,只能用于交互式容器(如问题使用)。
    • 这应该是公认的答案,包括@taranaki 的评论,Ctrl+P,Q 不适用于php:7.3-apache
    【解决方案7】:

    我对此进行了深入研究,上面的所有答案都部分正确。这完全取决于容器的启动方式。容器启动时归结为以下几点:

    • 已分配 TTY (-t)
    • 标准输入处于打开状态 (-i)

    ^P^Q 确实有效,但仅当-t-i 用于启动容器时:

    [berto@g6]$ docker run -ti -d --name test python:3.6 /bin/bash -c 'while [ 1 ]; do sleep 30; done;'
    b26e39632351192a9a1a00ea0c2f3e10729b6d3e22f8e0676d6519e15c08b518
    
    [berto@g6]$ docker attach test
    # here I typed ^P^Q
    read escape sequence
    
    # i'm back to my prompt
    [berto@g6]$ docker kill test; docker rm -v test
    test
    test
    

    ctrl+c 确实有效,但仅当-t没有-i)用于启动容器时:

    [berto@g6]$ docker run -t -d --name test python:3.6 /bin/bash -c 'while [ 1 ]; do sleep 30; done;'
    018a228c96d6bf2e73cccaefcf656b02753905b9a859f32e60bdf343bcbe834d
    
    [berto@g6]$ docker attach test
    ^C
    
    [berto@g6]$    
    

    第三种分离方式

    有一种方法可以在不杀死容器的情况下分离;你需要另一个外壳。总之,在另一个 shell 中运行它会分离并让容器运行pkill -9 -f 'docker.*attach'

    [berto@g6]$ docker run -d --name test python:3.6 /bin/bash -c 'while [ 1 ]; do sleep 30; done;'
    b26e39632351192a9a1a00ea0c2f3e10729b6d3e22f8e0676d6519e15c08b518
    
    [berto@g6]$ docker attach test
    # here I typed ^P^Q and doesn't work
    ^P
    # ctrl+c doesn't work either
    ^C
    # can't background either
    ^Z
    
    # go to another shell and run the `pkill` command above
    
    # i'm back to my prompt
    [berto@g6]$
    

    为什么?因为您正在杀死将您连接到容器的进程,而不是容器本身。

    【讨论】:

    • 第三种方式适合我。谢谢。如果您要附加到多个实例并且只想从一个实例中分离。可以杀死具体进程:ps -ef | grep 附加 -> 获取 pid。然后:杀死 -9
    • pkill 是 docker attach 之后唯一对我有用的东西
    • 为什么我们需要-9。我注意到如果我们不使用 -9 它会关闭容器。
    • 其他信号就是那个,信号。他们告诉进程什么类型的信号,并给它一个行动和做某事的机会。 kill -9 信号没有。该过程被终止并且没有追索权。我的猜测是其他信号让容器有机会关闭,而-9 没有。
    • 这非常有帮助。谢谢!
    【解决方案8】:

    您可以在运行docker attach 时使用--detach-keys 选项覆盖默认的CTRL+PCTRL + Q 序列(并不总是有效)。

    例如,当您运行 docker attach --detach-keys="ctrl-a" test 并按下 CTRL+A 时,您将退出容器,而不会杀死它。

    其他例子:

    • docker attach --detach-keys="ctrl-a,x" test - 按CTRL+A,然后按X 退出
    • docker attach --detach-keys="a,b,c" test - 按A,然后按B,然后按C 退出

    摘自官方文档:

    如果需要,您可以配置覆盖 Docker 键序列以进行分离。如果 Docker 默认序列与您用于其他应用程序的键序列冲突,这很有用。有两种方法可以定义您自己的分离键序列,作为每个容器的覆盖或作为整个配置的配置属性。

    要覆盖单个容器的序列,请在 docker attach 命令中使用--detach-keys="<sequence>" 标志。 <sequence> 的格式可以是字母[a-Z],也可以是ctrl- 与以下任意组合:

    • a-z(单个小写字母字符)
    • @(在符号处)
    • [(左括号)
    • \(两个反斜杠)
    • _(下划线)
    • ^(插入符号)

    这些actrl-aXctrl-\\ 值都是有效键序列的示例。要为所有容器配置不同的配置默认键序列,请参阅Configuration 文件部分。

    注意:这从 docker 版本 1.10+ 开始有效(在本回答时,当前版本是 18.03)

    【讨论】:

      【解决方案9】:

      如果您只想查看在容器内运行的进程的输出,您可以执行简单的docker container logs -f <container id>

      -f 标志使容器的输出为followed 并实时更新。对于调试或监控非常有用。

      【讨论】:

        【解决方案10】:

        旧帖子但退出然后重新启动...问题是如果您在 Windows 机器上 Ctrl p 或 Ctrl P 绑定到打印...退出启动容器不应该伤害任何东西

        【讨论】:

        • 除非您在生产系统上
        【解决方案11】:

        您可以通过发送 SEGKILL 来简单地终止 docker cli 进程。如果你用

        启动容器

        docker run -it some/container

        你可以得到它的pid

        ps -aux | grep docker

        user   1234  0.3  0.6 1357948 54684 pts/2   Sl+  15:09   0:00 docker run -it some/container
        

        假设它是 1234,你可以用它“分离”它

        kill -9 1234

        这有点像黑客,但它有效!

        【讨论】:

          【解决方案12】:

          在 Docker 容器中至少必须运行一个进程,然后只有容器会在后台不退出

          例如在 ubuntu docker 镜像中,

          要创建一个具有分离模式的新容器(至少在进程上运行后台),

          docker run -d -i -t f63181f19b2f /bin/bash
          

          它将为此图像(ubuntu)id f63181f19b2f 创建一个新的包含。容器将以分离模式(在后台运行)运行,此时一个小进程tty bash shell 将在后台运行。因此,容器将继续运行,直到 bash shell 进程被终止。

          要附加到正在运行的后台容器,请使用

          docker attach  b1a0873a8647
          

          如果你想在不退出的情况下从容器中分离(不杀死 bash shell), 默认情况下,您可以使用ctrl-p,q。它会在不退出容器的情况下从容器中出来(运行后台。这意味着不会杀死 bash shell)。

          您可以在附加时间将自定义命令传递给容器,

          docker attach --detach-keys="ctrl-s" b1a0873a8647
          

          这次ctrl-p,q 转义序列不起作用。相反,ctrl-s 将用于从容器中退出。您可以传递任何密钥,例如(ctrl-*)

          【讨论】:

          • 我已经多次在有关此主题的 Stack Overflow 答案之间切换选项卡,这是最简单、简单、完整且直截了当的答案。谢谢老哥
          【解决方案13】:

          如果你在 windows 上使用 docker,你可以使用组合 'CTRL + D'

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-09-22
          • 2016-02-22
          • 2015-03-04
          • 2011-10-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多