Linux

“輸入設備不是 TTY”在“docker run”輸出中究竟是什麼意思?

  • December 4, 2021

這是一個有效的命令:

$ 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 rundocker run/exec在將其傳遞給cat. 這就是為什麼input device is not a TTY如果你嘗試會得到 a 的echo "hello" | docker run -it alpine cat原因,因為在這種情況下,docker run自身的輸入是來自前一個 echo 的管道,而不是docker run執行的終端

最後,為什麼你需要通過-tif-i將你的輸入連接到輸入的技巧cat?這是因為如果輸入是終端,命令會以不同的方式處理輸入。這也是最好的例子

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p會給你一個密碼提示。如果您鍵入密碼,則字元會明顯列印出來。
  • docker run -i alpine sh會給你一個空行。如果你鍵入一個命令,就像ls你得到一個輸出一樣,但你不會得到一個提示或彩色輸出。

在最後兩種情況下,您會得到這種行為,因為mysql沒有shell將輸入視為 tty,因此沒有使用 tty 特定行為,例如屏蔽輸入或著色輸出。

引用自:https://serverfault.com/questions/897847