web-dev-qa-db-ja.com

「docker run」出力で「入力デバイスがTTYではない」とはどういう意味ですか?

これは機能するコマンドです。

$ echo 'hi there' | docker run -i ubuntu cat
hi there

これは、エラーメッセージで応答するコマンドです。

$ echo 'hi there' | docker run -it ubuntu cat
the input device is not a TTY

ここで何が起こっているのか正確に理解したいと思います。 「-tを削除すれば修正される」だけではありません。

そんなこと知ってる docker run-tオプションは "Allocate a pseudo-TTY"を意味し、 TTYの意味の歴史的概要 を読みましたが、ここで違反している契約の種類を理解するのに役立ちませんでした。

19
Mikhail Vasin

この回答 頭を回すのに役立ちました:

  • デフォルトでは(どちらもなし-iまたは-tオプション)Dockerコンテナーは、その出力をSTDOUTにのみ送信します。
  • -iオプションはSTDINへの接続が付属しています。
  • -tオプションは、STDIN/STDOUTの上で動作するターミナルインターフェイスドライバーを取り込みます。また、ターミナルドライバーがプルされると、コンテナーとの通信は ターミナルインターフェイスプロトコル に準拠する必要があります。文字列のパイピングは行いません。
8
Mikhail Vasin

遅い答えですが、誰かを助けるかもしれません

docker run/exec -iは、コンテナー内のコマンドのSTDINをdocker run/exec自体のSTDINに接続します。

そう

  • docker run -i Alpine catは、入力を待つ空の行を提供します。 「hello」と入力すると、エコー「hello」が表示されます。メインプロセスcatdocker runのターミナル入力である無限ストリームからの入力を待機しているため、CTRL + Dを送信するまでコンテナーは終了しません。
  • 一方、_catは入力ストリームが終了し、それ自体を終了するため、echo "hello" | docker -i run Alpine catは「hello」を出力してすぐに終了します。

上記のいずれかを終了した後でdocker psを試しても、実行中のコンテナは見つかりません。どちらの場合も、cat自体が終了したため、dockerはコンテナーを終了しました。

ここで「-t」の場合、これはdocker内のメインプロセスに、その入力が端末デバイスであることを伝えます。

そう

  • docker run -t Alpine catを指定すると空の行が表示されますが、「hello」と入力してもエコーは表示されません。これは、catが端末入力に接続されているが、この入力は入力に接続されていないためです。入力した "hello"はcatの入力に到達しませんでした。 catは、到着しない入力を待っています。
  • echo "hello" | docker run -t Alpine catも空の行を提供し、CTRL-Dでコンテナを終了しませんが、-iを渡さなかったため、エコー "hello"は表示されません。

CTRL + Cを送信するとシェルが元に戻りますが、docker psを今すぐ試すと、catコンテナーがまだ実行されていることがわかります。これは、閉じられなかった入力ストリームをcatがまだ待機しているためです。 -tと組み合わせずに、-iのみを使用する便利な方法は見つかりませんでした。

さて、一緒に-itを。これはcatにその入力がターミナルであることを伝え、同時にこのターミナルをターミナルであるdocker runの入力に接続します。 docker run/execは、catに渡す前に、自身の入力が実際にttyであることを確認します。 input device is not a TTYを入力するとecho "hello" | docker run -it Alpine catが取得されるのはこのためです。この場合、docker run自体の入力は、以前のエコーからのパイプであり、docker runが実行されるターミナルではありません。

最後に、-tが入力をcatの入力に接続するトリックを行うのであれば、なぜ-iを渡す必要があるのでしょうか。これは、コマンドが端末の場合、入力の扱いが異なるためです。これも例によって最もよく示されています

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -pは、パスワードプロンプトを表示します。パスワードを入力すると、文字が表示されます。
  • docker run -i Alpine shは空の行を提供します。 lsのようなコマンドを入力すると、出力は表示されますが、プロンプトや色付きの出力は表示されません。

最後の2つのケースでは、mysqlShellが入力をttyとして処理せず、入力のマスキングや出力のカラーリングなどのtty固有の動作を使用しなかったため、この動作が発生します。 。

9
Ahmed Ghonim

Ttyは、端末があることを示します。これは、xtermまたは多くのLinuxコマンドラインインターフェイスの1つによって提供されるものです。キーボードとそれに関連付けられたテキスト出力インターフェイスが必要です。これが必要になる一般的な理由は、カラーテキスト出力のサポート、さまざまなキーの組み合わせ(矢印キーなど)の処理、および画面上でカーソルを移動する機能のためです。

echoの例が示すようにコマンドをdockerにパイプすると、そのパイプは入力であり、そのパイプにはttyインターフェースがなく、単なるテキストのストリームです。エラーメッセージが示すように、それでttyを作成しようとすると失敗します。

4
BMitch