1. ホーム
  2. linux

docker attach」がハングするのはなぜですか?

2023-08-24 04:27:43

質問

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

どのように解決するのですか?

それは本当に ハング . 下のコメントにもあるように(You are running " /bin/bash をコマンドとして実行している)ように、アタッチする際に期待される動作であるようです。

私の理解では、実行中のシェルにアタッチすると、stdin/stdout/stderr は - run コマンドで渡したオプションに依存しますが - 単に出入りするものを表示するだけです。 その瞬間から . (もう少し深い知識をお持ちの方なら、より高いレベルで説明できると思います)。

質問に対するコメントで書いたように、docker github repoで同様の挙動を説明するissueを開いている人が何人もいます。

シェルと言うからには、既にシェルが起動しているのでしょう。 attach は新しいプロセスを開始しないので、実行中のプロセスの in/out/err ストリームに接続するのは、どのような動作が期待できるのでしょうか。 これは考えていませんでした。もちろん、これは実行中のシェルにアタッチする際に期待される動作ですが、望ましいことなのでしょうか?

docker attach で stdout/stderr をフラッシュし、それによってシェルプロンプトを強制的に表示させることは可能でしょうか、それとももう少し複雑なのでしょうか?個人的には、すでに実行されているシェルにアタッチする場合、これが期待されることです。

必要であれば、この問題をクローズしていただいて構いません。

  • から引用した コメント に、この github issue . この問題のコメントでより多くの洞察を得ることができます。

もし、代わりに enter の代わりに、コマンドを入力し始めると、その時点で 余分な のプロンプト行は表示されません。もし、あなたが

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

ここで <container-ID-or-name> を実行した後のコンテナの ID または名前です。 docker run -it -d ubuntu (を実行した後(つまり質問では3aef6e642327またはcondescending_sammet)、次のように実行されます。 新しい コマンドを実行するので、既存のコマンドにアタッチする際の "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

あなたは、1秒ごとに時間をプリントアウトするコンテナに取り付けられることになります。(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 を別のプログラムに置き換えることもできます。