これは機能するコマンドです。
$ 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の意味の歴史的概要 を読みましたが、ここで違反している契約の種類を理解するのに役立ちませんでした。
この回答 頭を回すのに役立ちました:
-i
または-t
オプション)Dockerコンテナーは、その出力をSTDOUTにのみ送信します。-i
オプションはSTDINへの接続が付属しています。-t
オプションは、STDIN/STDOUTの上で動作するターミナルインターフェイスドライバーを取り込みます。また、ターミナルドライバーがプルされると、コンテナーとの通信は ターミナルインターフェイスプロトコル に準拠する必要があります。文字列のパイピングは行いません。遅い答えですが、誰かを助けるかもしれません
docker run/exec -i
は、コンテナー内のコマンドのSTDINをdocker run/exec
自体のSTDINに接続します。
そう
docker run -i Alpine cat
は、入力を待つ空の行を提供します。 「hello」と入力すると、エコー「hello」が表示されます。メインプロセスcat
がdocker 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つのケースでは、mysql
とShell
が入力をttyとして処理せず、入力のマスキングや出力のカラーリングなどのtty固有の動作を使用しなかったため、この動作が発生します。 。
Ttyは、端末があることを示します。これは、xtermまたは多くのLinuxコマンドラインインターフェイスの1つによって提供されるものです。キーボードとそれに関連付けられたテキスト出力インターフェイスが必要です。これが必要になる一般的な理由は、カラーテキスト出力のサポート、さまざまなキーの組み合わせ(矢印キーなど)の処理、および画面上でカーソルを移動する機能のためです。
echo
の例が示すようにコマンドをdockerにパイプすると、そのパイプは入力であり、そのパイプにはttyインターフェースがなく、単なるテキストのストリームです。エラーメッセージが示すように、それでttyを作成しようとすると失敗します。