为什么“docker attach”会挂起?

新手上路,请多包涵

我可以成功运行 ubuntu 容器:

 # docker run -it -d ubuntu
3aef6e642327ce7d19c7381eb145f3ad10291f1f2393af16a6327ee78d7c60bb
# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
3aef6e642327        ubuntu              "/bin/bash"         3 seconds ago       Up 2 seconds                            condescending_sammet

但执行 docker attach 挂起:

 # docker attach 3aef6e642327

直到我按下任意键,例如 Enter

 # docker attach 3aef6e642327
root@3aef6e642327:/#
root@3aef6e642327:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

为什么 docker attach 挂起?

更新

阅读评论后,我想我得到了答案:

先决条件:

“docker attach”重用相同的 tty,而不是打开新的 tty。

(1) 无守护模式执行 docker run

 # docker run -it ubuntu
root@eb3c9d86d7a2:/#

一切OK,然后运行 ls 命令:

 root@eb3c9d86d7a2:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@eb3c9d86d7a2:/#

(2) 在守护模式下运行 docker run

 # docker run -it -d ubuntu
91262536f7c9a3060641448120bda7af5ca812b0beb8f3c9fe72811a61db07fc

实际上, 以下内容应该已经从正在运行的容器输出到标准输出:

 root@91262536f7c9:/#

所以执行 docker attach 似乎挂起,但实际上它正在等待您的输入:

 # docker attach 91262536f7c9
ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@91262536f7c9:/#

原文由 Nan Xiao 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 849
2 个回答

它并没有真正 _挂起_。正如您在下面的评论中看到的(您正在运行“ /bin/bash ”作为命令),附加时似乎是预期的行为。

据我了解,您附加到正在运行的 shell 中,而 stdin/stdout/stderr(取决于您与运行命令一起传递的选项)只会向您显示 从那一刻起 进入/退出的任何内容。 (希望有更深入知识的人可以在更高层次上解释这一点)。

正如我在对您的问题的评论中所写的那样,有几个人在 docker github repo 上打开了一个问题,描述了类似的行为:

既然你提到了 shell,我假设你已经有一个 shell 正在运行。 attach 不会启动新进程,那么连接到正在运行的进程的输入/输出/错误流的预期行为是什么?我没有考虑到这一点。当然,这是附加到正在运行的 shell 的预期行为,但这是可取的吗?

是否有可能在 docker attach 上刷新 stdout/stderr 从而强制打印 shell 提示符,还是比这更复杂一些?这就是我个人在附加到已经运行的 shell 时所“期望”的。

如有必要,请随时关闭此问题,我只是觉得有必要记录下来并获得一些反馈。

  • 取自 对此 github 问题 的评论。您可以在此问题的评论中找到更多见解。

如果不是 enter 您将开始输入命令,您将不会看到 额外的 空提示行。如果你要跑

$ docker exec -it ubuntu <container-ID-or-name> bash

其中 <container-ID-or-name> 是运行后容器的 ID 或名称 docker run -it -d ubuntu (所以 3aef6e642327 或 condescending_sammet 在你的问题中)它将运行一个 命令,因此没有这个“标准输出问题”附加到现有的。

例子

如果您在包含以下内容的目录中有 Dockerfile

 FROM ubuntu:latest
ADD ./script.sh /timescript.sh
RUN chmod +x /timescript.sh
CMD ["/timescript.sh"]

并在同一目录中有一个简单的 bash 脚本 script.sh 包含:

 #!/bin/bash

#trap ctrl-c and exit, couldn't get out
#of the docker container once attached
trap ctrl_c INT
function ctrl_c() {
    exit
}

while true; do
    time=$(date +%N)
    echo $time;
    sleep  1;
done

然后构建(在此示例中与 Dockerfile 和 script.sh 位于同一目录中)并运行它

$ docker build -t nan-xiao/time-test .
..stuff happening...
$ docker run -itd --name time-test nan-xiao/time-test

最后 attach

 $ docker attach time-test

您最终将连接到一个容器,每秒打印出时间。 (CTRL-C 退出)

示例 2

或者,如果您有 Dockerfile 包含例如以下内容:

 FROM ubuntu:latest
RUN apt-get -y install irssi
ENTRYPOINT ["irssi"]

然后在同一目录下运行:

 $ docker build -t nan-xiao/irssi-test .

然后运行它:

 $ docker run -itd --name irssi-test nan-xiao/irssi-test

最后

$ docker attach irssi-test

如果没有这种特殊行为,您最终会进入一个正在运行的 irssi 窗口。当然你可以用 irrsi 代替另一个程序。

原文由 Francesco de Guytenaere 发布,翻译遵循 CC BY-SA 3.0 许可协议

在尝试附加到由其他人开发并且已经运行守护程序的容器时,我也遇到了这个问题。 (在这种情况下,它是 LinuxServer 的 transmission 镜像)。

问题:

发生的事情是终端似乎“挂起”,输入任何内容都无济于事,也不会出现。只有 Ctrl-C 会把我踢出去。

docker run , docker start , docker attach all was not successful, turns out the command I needed (after the container has been started with run or start ) 是执行 bash ,因为您从中提取的容器可能没有 bash 已经运行。

解决方案:

docker exec -it <container-id> bash

(您可以通过运行 docker ps -a container-id

这会将您拉入具有功能性 bash 的实例 root (假设您拉出的图像没有进行其他显式设置)。

我知道接受的答案也抓住了这一点,但决定发布另一个更简洁明了的答案,因为当我阅读它时,解决方案没有为我弹出。

原文由 matrixanomaly 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题