Dies ist ein Befehl, der funktioniert:
$ echo 'hi there' | docker run -i ubuntu cat
hi there
Dies ist ein Befehl, der mit einer Fehlermeldung antwortet:
$ echo 'hi there' | docker run -it ubuntu cat
the input device is not a TTY
Ich möchte genau herausfinden, was hier passiert. Nicht einfach „remove -t und es wird behoben“.
Ich weiß, dass docker run
die -t
Option für "Allocate a pseudo-TTY" steht, und ich habe gelesenhistorische Übersichten darüber, wofür TTY steht, aber es hat mir nicht geholfen zu verstehen, gegen welche Art von Vertrag hier verstoßen wird.
Antwort1
Späte Antwort, könnte aber jemandem helfen
docker run/exec -i
verbindet die STDIN des Befehls im Container mit der STDIN docker run/exec
selbst.
Also
docker run -i alpine cat
gibt Ihnen eine leere Zeile, die auf eine Eingabe wartet. Geben Sie „hallo“ ein, Sie erhalten ein Echo „hallo“. Der Container wird erst beendet, wenn Sie STRG+D senden, da der Hauptprozesscat
auf eine Eingabe aus dem unendlichen Stream wartet, der die Terminaleingabe des istdocker run
.- Andererseits
echo "hello" | docker run -i alpine cat
wird „Hallo“ gedruckt und das Programm wird sofort beendet, weilcat
es erkennt, dass der Eingabestrom zu Ende ist, und sich selbst beendet.
Wenn Sie es docker ps
nach dem Beenden eines der oben genannten Programme versuchen, werden Sie keine laufenden Container finden. In beiden Fällen cat
wurde Docker selbst beendet, sodass Docker den Container beendet hat.
Nun zu „-t“: Dies teilt dem Hauptprozess im Docker mit, dass seine Eingabe ein Terminalgerät ist.
Also
docker run -t alpine cat
gibt Ihnen eine leere Zeile, aber wenn Sie versuchen, „hallo“ einzugeben, erhalten Sie kein Echo. Das liegt daran, dass zwarcat
mit einem Terminaleingang verbunden ist, dieser Eingang jedoch nicht mit Ihrem Eingang verbunden ist. Das von Ihnen eingegebene „hallo“ hat den Eingang von nicht erreichtcat
.cat
wartet auf einen Eingang, der nie eintrifft.echo "hello" | docker run -t alpine cat
gibt Ihnen auch eine leere Zeile und verlässt den Container nicht mit STRG-D, aber Sie erhalten kein Echo "Hallo", weil Sie nicht übergeben haben-i
Wenn Sie STRG+C senden, erhalten Sie Ihre Shell zurück, aber wenn Sie es docker ps
jetzt versuchen, sehen Sie, dass der cat
Container immer noch läuft. Das liegt daran, cat
dass immer noch auf einen Eingabestream wartet, der nie geschlossen wurde. Ich habe keine sinnvolle Verwendung für -t
alleiniges Verwenden von gefunden, ohne es mit zu kombinieren -i
.
Nun zu -it
zusammen. Dies teilt cat mit, dass sein Eingang ein Terminal ist und verbindet gleichzeitig dieses Terminal mit dem Eingang von , docker run
der ein Terminal ist. docker run/exec
stellt sicher, dass sein eigener Eingang tatsächlich ein tty ist, bevor es an weitergegeben wird cat
. Deshalb erhalten Sie ein , input device is not a TTY
wenn Sie versuchen echo "hello" | docker run -it alpine cat
, weil in diesem Fall der Eingang von docker run
sich selbst die Pipe vom vorherigen Echo ist und nicht das Terminal, auf dem docker run
ausgeführt wird
Und schließlich: Warum müssen Sie -t
„if -i
will“ übergeben, um Ihre Eingabe mit der Eingabe von zu verbinden cat
? Dies liegt daran, dass Befehle die Eingabe anders behandeln, wenn es sich um ein Terminal handelt. Dies lässt sich auch am besten anhand eines Beispiels veranschaulichen.
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p
wird Ihnen eine Passwortabfrage angezeigt. Wenn Sie das Passwort eingeben, werden die Zeichen sichtbar gedruckt.docker run -i alpine sh
gibt eine leere Zeile aus. Wenn Sie einen Befehl wiels
diesen eingeben, erhalten Sie eine Ausgabe, aber keine Eingabeaufforderung oder farbige Ausgabe.
In den letzten beiden Fällen tritt dieses Verhalten auf, weil wir die Eingabe mysql
nicht shell
als TTY behandelt haben und daher kein TTY-spezifisches Verhalten wie das Maskieren der Eingabe oder das Einfärben der Ausgabe verwendet haben.
Antwort2
Diese Antworthat mir geholfen, das zu verstehen:
- Standardmäßig (ohne die Optionen „weder
-i
noch“-t
) sendet ein Docker-Container seine Ausgabe nur an STDOUT. - mit
-i
Option kommt Anschluss an STDIN, -t
Option zieht einen Terminalschnittstellentreiber ein, das auf STDIN/STDOUT basiert. Und wenn ein Terminaltreiber eingebunden wird, muss die Kommunikation mit einem Container denTerminal-Schnittstellenprotokoll. Das Weiterleiten einer Zeichenfolge funktioniert nicht.
Antwort3
Ein tty zeigt an, dass Sie ein Terminal haben, das von xterm oder einer der vielen Linux-Befehlszeilenschnittstellen bereitgestellt wird. Es muss eine Tastatur und eine zugehörige Textausgabeschnittstelle haben. Typische Gründe dafür sind die Unterstützung der Farbtextausgabe, die Handhabung verschiedener Tastenkombinationen (wie der Pfeiltasten) und die Möglichkeit, den Cursor über den Bildschirm zu bewegen.
Wenn Sie einen Befehl wie in Ihrem Beispiel gezeigt in Docker weiterleiten echo
, ist diese Pipe die Eingabe und diese Pipe hat keine TTY-Schnittstelle, sondern nur einen Textstrom. Der Versuch, damit ein TTY zu erstellen, schlägt fehl, wie die Fehlermeldung angibt.