解決策 1:
遅い回答ですが、誰かを助けるかもしれません
docker run/exec -i
コンテナ内のコマンドの STDIN を docker run/exec
の STDIN に接続します 自体。
だから
docker run -i alpine cat
入力を待つ空の行を提供します。 「hello」と入力すると、「hello」というエコーが返されます。メインプロセスcat
がdocker run
の端末入力である無限ストリームからの入力を待っています .- 一方、
echo "hello" | docker -i run alpine cat
cat
であるため、"hello" を出力してすぐに終了します。 入力ストリームが終了したことを認識し、それ自体を終了します。
docker ps
を試すと 上記のいずれかを終了すると、実行中のコンテナーは見つかりません。どちらの場合も cat
自体が終了したため、docker はコンテナーを終了しました。
"-t" の場合、これは docker 内のメイン プロセスに、その入力が端末デバイスであることを伝えます。
だから
docker run -t alpine cat
空行が表示されますが、「hello」と入力しようとすると、エコーは得られません。これはcat
の間 端末入力に接続されている場合、この入力は入力に接続されていません。入力した「こんにちは」が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
を渡す必要があるのでしょうか? -i
の場合 入力を cat
に接続するトリックを行います の入力?これは、コマンドが端末の場合、入力の扱いが異なるためです。これも例によって最もよく説明されています
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p
パスワードプロンプトが表示されます。パスワードを入力すると、文字がはっきりと印刷されます。docker run -i alpine sh
空行が表示されます。ls
のようなコマンドを入力すると 出力は得られますが、プロンプトや色付きの出力は得られません。
最後の 2 つのケースでは、mysql
が原因でこの動作が発生します。 shell
と同様 入力を tty として扱っていなかったため、入力のマスキングや出力の色付けなどの tty 固有の動作を使用していませんでした。
解決策 2:
この回答は、頭を整理するのに役立ちました:
- デフォルト (
-i
なし)-t
でもありません オプション) Docker コンテナはその出力のみを STDOUT に送信します。 -i
で オプションは STDIN への接続、-t
オプションはターミナル インターフェイス ドライバを取り込みます 、STDIN/STDOUT の上で動作します。また、ターミナル ドライバが取り込まれると、コンテナとの通信はターミナル インターフェイス プロトコルに準拠する必要があります。文字列をパイプすることはできません。
解決策 3:
tty は、xterm または多くの Linux コマンドライン インターフェイスの 1 つによって提供される端末があることを示します。それに関連付けられたキーボードとテキスト出力インターフェイスが必要です。これが必要な一般的な理由は、カラー テキスト出力のサポート、さまざまなキーの組み合わせ (矢印キーなど) の処理、および画面上でカーソルを移動する機能です。
echo
のようなコマンドを docker にパイプすると、 例が示すように、パイプは入力であり、そのパイプには tty インターフェイスがなく、単なるテキスト ストリームです。エラーメッセージが示すように、これを使用して tty を作成しようとすると失敗します。