为什么“docker attach”会挂起?

时间:2016-02-23 09:33:18

标签: linux docker 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

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

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

7 个答案:

答案 0 :(得分:27)

它实际上没有挂起。正如您在下面的注释中所看到的(您正在运行“/bin/bash”作为命令),它似乎是附加时的预期行为。

据我所知,你附加到正在运行的shell,只有stdin / stdout / stderr - 取决于你传递的选项和运行命令 - 只会显示进出的内容 从那一刻起 。 (有更多深入知识的人希望能够在更高层次上解释这一点)。

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

  
    

既然你提到了shell,我假设你已经运行了一个shell。 attach不会启动新进程,那么连接到正在运行的进程的in /​​ out / err流的预期行为是什么?     我没想到这个。当然这是附加到正在运行的shell的预期行为,但这是否可取?

  
     

是否可以在docker attach上刷新stdout / stderr,从而强制打印shell提示符,或者它是否比这更复杂?这是我个人在连接到已经运行的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问题”。

实施例

如果您在目录中包含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替换为另一个程序。

答案 1 :(得分:14)

当我尝试连接到由其他人开发并且已经运行守护程序的容器时,我也遇到了这个问题。 (在这种情况下,它是LinuxServer&#39; s transmission docker image)。

问题:

终端似乎发生了什么事情,其中​​输入任何内容并没有帮助,也不会显示出来。只有Ctrl-C会让我退缩。

docker rundocker startdocker attach一切都没有成功,结果是我需要的命令(在使用runstart启动容器之后)是执行bash,因为你从中取出的容器没有bash已经运行。

解决方案:

docker exec -it <container-id> bash

(您可以从container-id)找到docker ps -a

这会将您带入功能重击为root的实例(假设您提取的图像没有进行其他显式设置)。

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

答案 2 :(得分:1)

由于以下原因,这件事发生在我身上:

可能是容器内的bash命令正在执行一个&#34; cat&#34;命令。

因此,当您附加到容器(bash命令)时,您实际上是在期望输入的cat命令中。 (文本和/或ctrl-d写文件)

答案 3 :(得分:1)

当我运行docker attach container-name时,没有任何输出,即使Ctrl-c无效。所以,先试试

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

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

docker exec -ti container-name bash

答案 4 :(得分:0)

如果您无法访问命令行,请确保在开始时使用-i标记运行容器。

答案 5 :(得分:0)

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

这就是我正在发生的事情:

docker-compose logs -f nginx
Attaching to laradock_nginx_1

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

docker ps -a表明该图像名称不存在应该被称为laradock_nginx的东西,所以我认为我只是要删除并重新“上载”该容器:

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现在可以工作了。

答案 6 :(得分:0)

使用:docker exec -it CONTAINER_ID/NAME bash

改为:docker attach...