これは機能するコマンドです:
$ 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
オプションは「疑似TTYを割り当てる」という意味だと知っています。TTY の歴史的概要しかし、ここでどのような契約違反が起こっているのか理解するのに役立ちませんでした。
答え1
遅い回答ですが、誰かの役に立つかもしれません
docker run/exec -i
コンテナ内のコマンドの STDIN をコンテナ自体の STDIN に接続しますdocker run/exec
。
それで
docker run -i alpine cat
入力を待つ空行が表示されます。「hello」と入力すると、「hello」というエコーが表示されます。メイン プロセスは、のターミナル入力である無限ストリームからの入力を待機しているため、CTRL+D を送信するまでコンテナーは終了しませんcat
。docker run
- 一方、入力ストリームが終了したことを検知して自身を終了する
echo "hello" | docker run -i alpine cat
ため、「hello」を出力してすぐに終了します。cat
上記のいずれかを終了した後に試すとdocker ps
、実行中のコンテナは見つかりません。どちらの場合も、dockercat
自体が終了しているため、docker がコンテナを終了しています。
ここで、「-t」は、入力が端末デバイスであることを docker 内のメイン プロセスに伝えます。
それで
docker run -t alpine cat
は空行を表示しますが、「hello」と入力してもエコーは表示されません。これは、 がcat
端末入力に接続されているのに対し、この入力はユーザーの入力に接続されていないためです。入力した「hello」は の入力に到達しませんでしたcat
。cat
は、決して到着しない入力を待機しています。echo "hello" | docker run -t alpine cat
空の行も表示され、CTRL-Dでコンテナから抜け出すことはできませんが、渡していないため、echo "hello"は表示されません。-i
CTRL+C を送信するとシェルが戻りますが、docker ps
今試してみると、cat
コンテナーがまだ実行中であることがわかります。これは、 が閉じられていない入力ストリームをまだ待機しているためです。と組み合わせずに を単独でcat
使用することの有用な用途は見つかりませんでした。-t
-i
さて、 を-it
一緒にします。これは cat にその入力が端末であることを伝え、同時にこの端末を の入力でdocker run
ある端末に接続します。 は、docker run/exec
それを に渡す前に、自身の入力が実際に tty であることを確認します。この場合、 の入力は前の echo からのパイプであり、が実行される端末ではないため、を試みると が返されるのはcat
そのためです。input device is not a TTY
echo "hello" | docker run -it alpine cat
docker run
docker run
最後に、入力を の入力に接続するの-t
に必要なのはなぜでしょうか? これは、コマンドがターミナルの入力を異なる方法で扱うためです。これは、例でもよくわかります。-i
cat
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p
パスワードプロンプトが表示されます。パスワードを入力すると、文字が目に見える形で印刷されます。docker run -i alpine sh
空行が表示されます。 のようなコマンドを入力するとls
出力は得られますが、プロンプトや色付きの出力は得られません。
最後の 2 つのケースでは、入力を tty として処理しなかったmysql
ため、入力のマスクや出力の色付けなどの tty 固有の動作を使用しなかったために、この動作が発生します。shell
答え2
この答え理解するのに役立ちました:
- デフォルトでは(オプション
-i
も指定しない場合-t
)、Dockerコンテナは出力をSTDOUTにのみ送信します。 - オプションで
-i
STDINに接続できます。 -t
オプションは端末インターフェースドライバをプルします、STDIN/STDOUT上で動作する。ターミナルドライバがプルインされると、コンテナとの通信は端末インターフェースプロトコル文字列をパイプすることはそうではありません。
答え3
tty は、xterm または多くの Linux コマンドライン インターフェイスのいずれかによって提供される端末があることを示します。これには、それに関連付けられたキーボードとテキスト出力インターフェイスが必要です。これを必要とする一般的な理由は、カラー テキスト出力のサポート、さまざまなキーの組み合わせ (矢印キーなど) の処理、および画面上でカーソルを移動する機能のためです。
例のようにコマンドを docker にパイプするとecho
、そのパイプが入力となり、そのパイプには tty インターフェイスがなく、単なるテキスト ストリームになります。これを使用して tty を作成しようとすると、エラー メッセージが示すように失敗します。