“輸入設備不是 TTY”在“docker run”輸出中究竟是什麼意思?
這是一個有效的命令:
$ 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
’s-t
選項代表“分配一個偽 TTY”,並且我已經閱讀了 TTY 代表什麼的歷史概述,但它並沒有幫助我理解這裡違反了什麼樣的契約。
這個答案幫助我解決了問題:
- 預設情況下(既沒有
-i
也沒有-t
選項)Docker 容器僅將其輸出發送到 STDOUT,- 可以
-i
選擇連接到 STDIN,-t
選項拉入終端介面驅動程序,該驅動程序在 STDIN/STDOUT 之上工作。並且當終端驅動被拉入時,與容器的通信必須符合終端介面協議。管道沒有。
遲到的答案,但可能會幫助某人
docker run/exec -i
將容器內命令的 STDIN 連接到docker run/exec
自身的 STDIN。所以
docker run -i alpine cat
給你一個空行等待輸入。輸入“你好”,你會得到一個迴聲“你好”。在您發送 CTRL+D 之前,容器不會退出,因為主程序cat
正在等待來自無限流的輸入,即docker run
.- 另一方面,
echo "hello" | docker run -i alpine cat
將列印“hello”並立即退出,因為cat
註意到輸入流已經結束並自行終止。如果您
docker ps
在退出上述任一方法後嘗試,您將找不到任何正在執行的容器。在這兩種情況下,cat
自身都已終止,因此 docker 已終止容器。現在對於“-t”,這告訴 docker 內部的主程序它的輸入是終端設備。
所以
docker run -t alpine cat
會給你一個空行,但如果你嘗試輸入“hello”,你將不會得到任何迴聲。這是因為雖然cat
連接到終端輸入,但此輸入未連接到您的輸入。您輸入的“你好”沒有到達cat
.cat
正在等待永遠不會到達的輸入。echo "hello" | docker run -t alpine cat
也會給你一個空行,並且不會在 CTRL-D 上退出容器,但你不會得到 echo “hello” 因為你沒有通過-i
如果您發送 CTRL+C,您將恢復您的 shell,但如果您
docker ps
現在嘗試,您會看到cat
容器仍在執行。這是因為cat
仍在等待從未關閉的輸入流。如果不-t
與-i
.現在,為了
-it
在一起。這告訴 cat 它的輸入是一個終端,同時將此終端連接到作為終端的輸入docker run
。docker run/exec
在將其傳遞給cat
. 這就是為什麼input device is not a TTY
如果你嘗試會得到 a 的echo "hello" | docker run -it alpine cat
原因,因為在這種情況下,docker run
自身的輸入是來自前一個 echo 的管道,而不是docker run
執行的終端最後,為什麼你需要通過
-t
if-i
將你的輸入連接到輸入的技巧cat
?這是因為如果輸入是終端,命令會以不同的方式處理輸入。這也是最好的例子
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p
會給你一個密碼提示。如果您鍵入密碼,則字元會明顯列印出來。docker run -i alpine sh
會給你一個空行。如果你鍵入一個命令,就像ls
你得到一個輸出一樣,但你不會得到一個提示或彩色輸出。在最後兩種情況下,您會得到這種行為,因為
mysql
沒有shell
將輸入視為 tty,因此沒有使用 tty 特定行為,例如屏蔽輸入或著色輸出。