为什么 "docker attach" 挂起?

Why does "docker attach" hang?

我可以 运行 一个 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:/# 

一切正常,然后运行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

实际上,以下内容应该从 运行ning 容器输出到标准输出:

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:/#

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

据我了解,您附加到 运行ning shell 和 stdin/stdout/stderr - 取决于您随 运行 命令传递的选项 -只会向您展示从那一刻起 in/out 发生的一切 。 (希望有更深入知识的人可以在更高层次上解释这一点)。

正如我在对您的问题的评论中所写,有几个人在 docker github 存储库上提出了一个问题,描述了类似的行为:

Since you mention shell, I assume you have a shell already running. attach doesn't start a new process, so what is the expected behavior of connecting to the in/out/err streams of a running process? I didn't think about this. Of course this is the expected behavior of attaching to a running shell, but is it desirable?

是否有可能在 docker attach 上刷新 stdout/stderr 从而强制打印 shell 提示符,还是比这更复杂一些?这就是我个人 "expect" 附加到已经 运行ning shell.

时的情况

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

如果您开始键入命令而不是 enter,您将不会看到 extra 空提示行。如果你要 运行

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

其中 <container-ID-or-name> 是您 运行 docker run -it -d ubuntu 之后容器的 ID 或名称(因此您的问题中的 3aef6e642327 或 condescending_sammet)它将 运行 new 命令,因此没有附加到现有命令的 "stdout problem"。

例子

如果您在包含以下内容的目录中有一个 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 window。当然,您可以用 irrsi 替换另一个程序。

我遇到过一次,原因如下:

可能是容器内的bash命令正在执行"cat"命令。

因此,当您附加到容器(bash 命令)时,您实际上在 cat 命令中,该命令正在等待输入。 (text and/or ctrl-d写入文件)

如果您无法访问命令行,请确保您 运行 您的容器在启动时带有 -i 标志。

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

问题:

发生的事情是终端出现在 'hang' 上,在那里输入任何内容都无济于事,也不会出现。只有 Ctrl-C 会把我踢出去。

docker rundocker startdocker attach 都没有成功,结果是我需要的命令(在使用 run 或 [=16 启动容器后=]) 是执行 bash,因为您从中拉出的容器很可能没有 bash 已经 运行.

解决方案:

docker exec -it <container-id> bash

(您可以从 运行 docker ps -a 中找到 container-id)。

这会将您拉入具有功能 bash 的实例,如 root(假设您拉取的图像没有完成其他显式设置)。

我知道已接受的答案也包含了这一点,但决定 post 另一个更简洁和明显的答案,因为当我阅读它时,解决方案并没有为我弹出.

当我运行docker attach container-name时,则没有任何输出,甚至Ctrl-c也是无效的。所以,先试试

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

然后ctrl-c可以阻止它。为什么它没有输出任何东西? 只是因为容器没有输出。实际上我需要输入我的容器和 运行 一些 shell 命令。所以正确的命令是

docker exec -ti container-name bash

我今天遇到了类似的问题并且能够解决它:

这是我遇到的情况:

docker-compose logs -f nginx
Attaching to laradock_nginx_1

然后它会挂在那里,直到我通过 CTRL-C 退出:^CERROR: Aborting.

docker ps -a 显示该图像名称不存在应该被称为 laradock_nginx 的内容,所以我想我只是删除并重新 "up" 那个容器:

docker stop cce0c32f7556
docker rm cce0c32f7556
docker-compose up -d laradock_nginx

不幸的是:ERROR: No such service: laradock_nginx

所以我做了 sudo reboot 然后 docker ps -a,但是 laradock_nginx 仍然不存在。

幸运的是,docker-compose up -d nginx 然后起作用了,docker-compose logs -f nginx 现在起作用了。

使用:docker exec -it CONTAINER_ID/NAME bash

改为:docker attach...