このオプションは正確に何をしますか?私はTTYをよく読んでいますが、まだ混乱しています。 -t
を持たず、単に-i
を持たずに遊んでみましたが、ユーザー入力を期待するプログラムは-t
なしでエラーをスローするようです。擬似TTYを有効にすることが重要なのはなぜですか?
「-t」オプションは、Unix/Linuxが端末アクセスを処理する方法に移動します。過去には、端末はハードライン接続で、後にモデムベースの接続でした。これらには物理的なデバイスドライバーがありました(実際の機器です)。一般化されたネットワークが使用されると、擬似端末ドライバが開発されました。これは、プログラムに直接書き込む必要なしに、どの端末機能を使用できるかを理解することを区別するためです(stty
、curses
のmanページを読んでください)。
したがって、それを背景として、オプションなしでコンテナを実行すると、デフォルトでstdoutストリームがあります(したがってdocker run | <cmd>
が機能します)。 「-i」で実行すると、stdinストリームが追加されます(したがって、<cmd> | docker run -i
は機能します)。通常は「-it」の組み合わせで「-t」を使用し、ターミナルドライバーを追加します。これは、プロセスと対話する場合に必要なものです。基本的に、コンテナの開始はターミナル接続セッションのように見えます。
「-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
これがお役に立てば幸いです!これが文書化されていない、またはあまり使用されていない理由はわかりません。おそらく実験的であり、今後のバージョンで文書化された機能として実装されるでしょう。
遅い答えですが、誰かを助けるかもしれません
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
が端末入力に接続されているが、この入力はユーザーの入力に接続されていないためです。入力した「ハロー」は、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固有の動作を使用しなかったため、この動作が発生します。
-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つは動作します。これが人々の役に立つことを願っています。