web-dev-qa-db-ja.com

擬似TTYを割り当てるためのDocker -tオプションについて混乱

このオプションは正確に何をしますか?私はTTYをよく読んでいますが、まだ混乱しています。 -tを持たず、単に-iを持たずに遊んでみましたが、ユーザー入力を期待するプログラムは-tなしでエラーをスローするようです。擬似TTYを有効にすることが重要なのはなぜですか?

155
user1099123

「-t」オプションは、Unix/Linuxが端末アクセスを処理する方法に移動します。過去には、端末はハードライン接続で、後にモデムベースの接続でした。これらには物理的なデバイスドライバーがありました(実際の機器です)。一般化されたネットワークが使用されると、擬似端末ドライバが開発されました。これは、プログラムに直接書き込む必要なしに、どの端末機能を使用できるかを理解することを区別するためです(sttycursesのmanページを読んでください)。

したがって、それを背景として、オプションなしでコンテナを実行すると、デフォルトでstdoutストリームがあります(したがってdocker run | <cmd>が機能します)。 「-i」で実行すると、stdinストリームが追加されます(したがって、<cmd> | docker run -iは機能します)。通常は「-it」の組み合わせで「-t」を使用し、ターミナルドライバーを追加します。これは、プロセスと対話する場合に必要なものです。基本的に、コンテナの開始はターミナル接続セッションのように見えます。

137
Twweeed

「-t」引数は、Googleの検索によると、十分に文書化されておらず、多くの人から頻繁に言及されていません。

Bashプロンプト(1.8.1の最新バージョン)で「docker」と入力してすべてのdocker client引数のリスト(あるべき)を表示しても表示されません。

実際、「docker -t --help」と入力してこの引数に関する特定のヘルプを取得しようとすると、驚くほど曖昧な応答が返されます。

「提供されているが定義されていないフラグ:-t」

したがって、この議論について混乱していることを非難することはできません!

Dockerのオンラインドキュメントには、「擬似ttyを割り当てる」ことが記載されており、-iとともに使用されることがよくあります。

https://docs.docker.com/reference/run/

素晴らしいjwilder/nginx-proxy Dockerコンテナのドキュメントで次のように使用されるのを見ました:

docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx

この場合、このドッカーコンテナー内の「仮想」tty(Bashコマンドプロンプト/端末)に出力を送信します。その後、dockerコマンド「docker logs CONTAINER」を実行して、この出力を確認できます。CONTAINERは、このコンテナーのIDの最初の数文字です。このCONTAINER IDは、「docker ps -a」と入力すると見つけることができます

次のリンクでこの「-t」引数について簡単に説明しました。「-tおよび-iフラグは擬似ttyを割り当て、接続されていなくてもstdinを開いたままにします。これにより、 bashプロンプトが実行されている限り、従来のVMのようなコンテナ。」

https://coreos.com/os/docs/latest/getting-started-with-docker.html

これがお役に立てば幸いです!これが文書化されていない、またはあまり使用されていない理由はわかりません。おそらく実験的であり、今後のバージョンで文書化された機能として実装されるでしょう。

66
Rich

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

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が端末入力に接続されているが、この入力はユーザーの入力に接続されていないためです。入力した「ハロー」は、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固有の動作を使用しなかったため、この動作が発生します。

16
Ahmed Ghonim

-tについて私が知っていることは次のとおりです。

docker exec -ti CONTAINER bash-コンテナに「ログイン」することができます。 ssh-ingのように感じます(そうではありません)。

しかし、問題は、データベースを復元したかったときです。

通常、dodocker exec -ti mysql.5.7 mysql-ここで、コンテナでmysqlコマンドを実行し、インタラクティブなターミナルを取得します。

前のコマンドに<dump.sqlを追加して、dbを復元できるようにしました。しかし、cannot enable tty mode on non tty inputで失敗しました。

-tの削除が役立ちました。それでも理由がわからない:

docker exec -i mysql.5.7 mysql < dump.sql

最後の1つは動作します。これが人々の役に立つことを願っています。

6
mist