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


207

このオプションは正確には何をしますか?私はTTYについてたくさん読んでいますが、それでも混乱しています。私は持っていないと周りの演奏-tだけを-iし、それがユーザーの入力をせずにエラーをスロー期待しているプログラムのように思えます-t。疑似TTYを有効にすることが重要なのはなぜですか?

回答:


223

-tオプションは、Unix / Linuxは、端末のアクセスをどのように処理するかに行きます。以前は、端末は固定回線接続でしたが、後でモデムベースの接続になりました。これらには物理的なデバイスドライバーがありました(実際の機器の一部でした)。一般化されたネットワークが使用されるようになると、疑似端末ドライバーが開発されました。それは、端末の能力は(上のmanページを読んで、直接あなたのプログラムにそれを記述する必要なしに使用することができるかを理解間の分離を作成するためですsttycurses)。

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


7
これが一番の答えです。ここでは最も技術的なものではありませんが、-itフラグの基本的な動作を説明しています。
クリスハイラ2018

1
クリスに同意します。私は他の答えを読みましたが、それでも完全に混乱しました。この答えはそれを明確にします。
ベン・リー

4
はい、「TTY」自体が「teletypewriter」(別名「teleprinter」)の頭字語であることを言及する価値はあります。電話のように、テキストを入力して同時に送信できるデバイスの名前でした。テキストの場合;-)試してみるdocker run -i ubuntudocker run -it ubuntu、すぐに違いがわかります。「-i」を使用すると、コンテナがホストからの対話を待機するようになりますが、フラグ「-t」を使用して「ttyドライバーを割り当て」た後、コンソール(ターミナル)からの実際の対話が可能になります。
Zegar

docker内でttyを起動できますか?でdockerを実行しないと動作を停止するアプリがあります-tが、本番環境ではdocker startコマンドを変更できません。だから私はそれがで始まったとアプリに思わせる必要があります-t
mvorisek

97

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

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

そう

  • docker run -i alpine cat入力を待つ空の行が表示されます。「hello」と入力すると、「hello」というエコーが表示されます。メインプロセスがの端末入力である無限ストリームからの入力を待機しているため、コンテナはCTRL+ を送信するまで終了しません。Dcatdocker run
  • 一方、入力ストリームが終了し、自分自身を終了したecho "hello" | docker run -i alpine catことをcat通知するため、「hello」を出力してすぐに終了します。

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

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

そう

  • docker run -t alpine cat空の行が表示されますが、「hello」と入力してもエコーは表示されません。これはcat、が端子入力に接続されているが、この入力は入力に接続されていないためです。入力した「hello」はの入力に到達しませんでしたcatcat到着しない入力を待っています。
  • echo "hello" | docker run -t alpine catまた、あなたの空行を与えるだろうと上のコンテナを終了していないだろうCTRL- Dしかし、あなたは合格しなかったので、あなたがエコー「こんにちは」を得ることはありません-i

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

今、-it一緒に。これは、入力が端子であることをcatに伝え、同時にこの端子を端子である入力に接続しdocker runます。docker run/execに渡す前に、自身の入力が実際にttyであることを確認しcatます。この場合、それ自体の入力は前のエコーからのパイプであり、実行される端末ではないため、これinput device is not a TTYを試してみるのecho "hello" | docker run -it alpine catはこのためです。docker rundocker run

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

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -u root -pパスワードプロンプトが表示されます。パスワードを入力すると、文字が表示されます。
  • docker run -i alpine sh空の行が表示されます。ls出力を取得するようなコマンドを入力しても、プロンプトやカラー出力は表示されません。

最後の2つのケースでは、この動作を得るmysqlだけでなく、としてshellの入力をマスキングまたは出力を着色するようにttyの特定の動作を使用していなかったので、ttyのように、入力を処理していなかったと。


6
ここでの最良の答えは、私に正確に何をするかを理解させ-t-iオプションが何をするかです!
Ruslan Stelmachenko

1
私が持っていたすべての質問を予測した素晴らしい答え
James Machin

@Ahmed Ghonim、非常に良い答え。ありがとうございました。しかし、「これは端末の場合、コマンドが入力を異なる方法で処理するためです」については、タイプミスだと思いますよね?「これは端末でない場合、コマンドは入力を異なる方法で処理するためです」であるはずですよね?
tuq

@Ahmed Ghonim。クリスタルクリア。しかし、docker run -a = stdin alpine catはどうですか?
HKIT

1
@HKIIT "-a = stdin"はstdinストリームをコンテナにアタッチしますが、メモリ割り当ては行いません。stdinストリームのコンテナーにバッファーメモリを割り当てるのは-iフラグです。したがって、-iが渡されると、アタッチメントフラグに関係なくstdinにメモリが割り当てられます。この割り当てられていないメモリがないと、標準入力への読み取りは空またはEOFになります。また、「-a = stdout」を含めて、catコマンドからの応答を確認する必要もあります。例:「docker run -i -a = stdin -a = stdout alpine cat」...もちろん、これを行う必要はありません。 「docker run -i alpine cat」を実行するだけです。
David D

71

-t引数には、Google検索によると、多くの場合、多くの人々によって十分に文書化、または言及されていません。

dockerBashプロンプト(最新バージョン1.8.1)で入力してすべてのDockerクライアント引数のリスト(表示されるはず)を表示しても表示されません。

実際、もしifと入力してこの引数について特定のヘルプを取得しようとすると、docker -t --help次の驚くほどあいまいな応答が返されます。

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

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

「疑似ttyを割り当てる」ことであり、多くの場合、 -i

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

私はそれjwilder/nginx-proxyが次のように素晴らしいドッカーコンテナのドキュメントで使用されているのを見ました:

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

この場合、何をするかは、このDockerコンテナー内の「仮想」tty(Bashコマンドプロンプト/ターミナル)に出力を送信することです。次に、dockerコマンドを実行してこの出力を確認できますdocker logs CONTAINERCONTAINER、このコンテナのIDの文字の最初のカップルです。このCONTAINER IDは、docker ps -a

私はこの-t議論が次のリンクで簡単に言及されているのを見ました、そこでそれは言います

-tそして-iフラグは仮想端末を割り当て、接続されていない場合でも、オープン標準入力ください。これにより、bashプロンプトが実行されている限り、従来のVMのようにコンテナーを使用できます。

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

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


21
ドキュメンテーションは、docker run --helpではなくに表示されますdocker -t --help-t, --tty=false Allocate a pseudo-TTY"
bskaggs

5

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

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

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

通常私はそうしますdocker 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つは動作します。これが人々の役に立つことを願っています。


docker内でttyを起動できますか?でdockerを実行しないと動作を停止するアプリがあります-tが、本番環境ではdocker startコマンドを変更できません。だから私はそれがで始まったとアプリに思わせる必要があります-t
mvorisek

1

Linuxでは、コマンドを実行するときに、コマンドを実行するために端末(tty)が必要です。

そのため、Dockerに接続する(または、Dockerコンテナーでコマンドを実行する)には、Dockerコンテナー内のターミナルを考慮に入れるオプション-tを指定する必要があります。


0

すべてのプロセスには3つのデータストリームがありますSTDIN/ STDOUT/ STDERR。プロセスがコンテナで実行されている場合、デフォルトでは、ターミナルはコンテナで実行されているプロセスのSTDOUTストリームに接続されます。したがってdocker run、ターミナルでコマンドを実行している間、すべての出力ストリームが表示されます。しかし、コンテナーで実行中のプロセスに入力を提供する場合は、プロセスのSTDINチャネルに接続する必要があります。これはデフォルトではなく、docker run -iコマンド。

-t インタラクティブ/フォーマットされた入力操作に使用されます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.