Mylić na temat opcji Docker -t, aby przydzielić pseudo-TTY


206

Co dokładnie robi ta opcja? Dużo czytam na TTY i wciąż jestem zdezorientowany. Bawiłem się z brakiem -ti po prostu -ii wydaje się, że programy, które oczekują, że dane wejściowe użytkownika będą zgłaszać błąd bez -t. Dlaczego włączenie pseudo-TTY jest ważne?

Odpowiedzi:


223

-tOpcja idzie jak Unix / Linux obsługuje dostęp do terminalu. W przeszłości terminal był połączeniem stacjonarnym, później połączeniem modemowym. Miały one fizyczne sterowniki urządzeń (były to prawdziwe urządzenia). Po uruchomieniu sieci uogólnionych opracowano sterownik pseudoterminalowy. Wynika to z tego, że tworzy on rozróżnienie między zrozumieniem, jakie możliwości terminala można wykorzystać bez potrzeby bezpośredniego zapisywania go w programie (czytaj strony podręcznika na stty,curses ).

Tak więc, mając to jako tło, uruchom kontener bez opcji i domyślnie masz standardowy strumień (tak docker run | <cmd>działa); uruchom z -i, a otrzymasz dodany strumień stdin (tak <cmd> | docker run -idziała); używaj -t, zwykle w kombinacji -iti masz dodany sterownik terminalu, który prawdopodobnie wchodzi w interakcję z procesem. Zasadniczo sprawia, że ​​kontener zaczyna wyglądać jak sesja połączenia terminala.


7
To powinna być najlepsza odpowiedź. Chociaż nie jest to tutaj najbardziej techniczny, wyjaśnia podstawowe zachowanie -itflag.
Kris Khaira

1
Zgadzam się z Kris. Przeczytałem inne odpowiedzi i nadal byłem całkowicie zdezorientowany. Ta odpowiedź wyjaśnia to.
Ben Lee,

3
Tak, może warto wspomnieć, że sam „TTY” to akronim pochodzący od słowa „teletypewriter” (AKA „teleprinter”), które było nazwą urządzenia umożliwiającego pisanie tekstu i wysyłanie go w tym samym czasie - jak telefon dla tekstu ;-) Spróbuj, docker run -i ubuntua docker run -it ubuntuzobaczysz różnicę natychmiast. „-i” pozwala zmusić kontener do oczekiwania na interakcję z hosta, ale faktyczna interakcja z konsoli (terminala) jest możliwa po „przydzieleniu sterownika tty” z flagą „-t”.
Zegar

Czy mogę uruchomić tty w oknie dokowanym? Mam aplikację, która przestaje działać, ale nie uruchamiam dokera -t, ale nie mogę modyfikować komendy uruchamiania dokera w środowisku produkcyjnym. Muszę więc sprawić, by aplikacja zaczęła myśleć -t.
mvorisek

97

Późna odpowiedź, ale może komuś pomóc

docker run/exec -ipołączy STDIN polecenia wewnątrz kontenera z STDIN docker run/execsamego.

Więc

  • docker run -i alpine catdaje pustą linię czekającą na dane wejściowe. Wpisz „cześć”, otrzymasz echo „cześć”. Kontener nie zostanie zamknięty, dopóki nie wyślesz CTRL+, Dponieważ główny proces catczeka na dane wejściowe ze strumienia nieskończonego, który jest wejściem końcowym pliku docker run.
  • Z drugiej strony echo "hello" | docker run -i alpine catwypisuje „cześć” i kończy natychmiast, ponieważ catzauważa, że ​​strumień wejściowy zakończył się i sam się zakończył.

Jeśli spróbujesz docker pspo wyjściu z jednego z powyższych, nie znajdziesz żadnych uruchomionych kontenerów. W obu przypadkach catsamo się zakończyło, więc doker zakończył kontener.

Teraz dla „-t” mówi to głównemu procesowi wewnątrz dokera, że ​​jego wejście jest urządzeniem końcowym.

Więc

  • docker run -t alpine catda ci pustą linię, ale jeśli spróbujesz wpisać „cześć”, nie dostaniesz żadnego echa. Wynika to z faktu, że chociaż catjest on podłączony do wejścia terminala, to wejście nie jest podłączone do twojego wejścia. Wpisane słowo „cześć” nie dotarło do wejścia cat. catczeka na dane wejściowe, które nigdy nie docierają.
  • echo "hello" | docker run -t alpine catda ci również pustą linię i nie opuści kontenera CTRL- Dale nie dostaniesz echa „cześć”, ponieważ nie przeszedłeś-i

Jeśli wyślesz CTRL+ C, odzyskasz swoją powłokę, ale jeśli spróbujesz docker psteraz, zobaczysz, że catkontener nadal działa. Jest tak, ponieważ catwciąż czeka na strumień wejściowy, który nigdy nie został zamknięty. Nie znalazłem żadnego przydatnego zastosowania dla -tsamego bez połączenia -i.

Teraz -itrazem. Mówi to kotowi, że jego wejściem jest terminal i jednocześnie podłącz ten terminal do wejścia, docker runktórego terminalem jest. docker run/execupewni się, że jego dane wejściowe są w rzeczywistości tty przed przekazaniem go cat. Dlatego dostaniesz a, input device is not a TTYjeśli spróbujesz, echo "hello" | docker run -it alpine catponieważ w tym przypadku wejściem docker runjest potok z poprzedniego echa, a nie terminal, w którym docker runjest wykonywany

Na koniec, dlaczego musiałbyś zdać, -tjeśli -ipodołasz, aby połączyć swój wkład z catwejściem? Jest tak, ponieważ polecenia traktują dane wejściowe inaczej, jeśli jest to terminal. Najlepiej ilustruje to również przykład

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -u root -pwyświetli monit o hasło. Jeśli wpiszesz hasło, znaki zostaną wydrukowane w widoczny sposób.
  • docker run -i alpine shda ci pustą linię. Jeśli wpiszesz polecenie, tak jak lsotrzymasz wynik, ale nie pojawi się monit lub kolorowe wyjście.

W dwóch ostatnich przypadkach, masz ten problem, bo mysqljak shellnie traktowali jako wejście tty, a zatem nie używać tty specyficzne zachowanie jak maskowanie wejścia lub kolorowania wyjście.


6
Najlepsza odpowiedź tutaj, która naprawdę pozwala mi zrozumieć, co dokładnie robią -ti jakie -iopcje!
Ruslan Stelmachenko

1
Fantastyczna odpowiedź, która wyprzedzała każde pytanie, które miałem
James Machin

@Ahmed Ghonim, Bardzo dobre odpowiedzi. Dziękuję Ci. Ale jeśli chodzi o „Dzieje się tak, ponieważ polecenia traktują dane wejściowe inaczej, jeśli jest to terminal”, myślę, że to pomyłka, prawda? Powinno być „To dlatego, że wejście polecenia traktować inaczej, czy to nie terminal”, prawda?
tuq

@Ahmed Ghonim. Krystalicznie czyste. Ale co z dokerem run -a = stdin alpine cat?
HKIT

1
@HKIIT "-a = stdin" dołącza strumień stdin do kontenera, ale bez przydziału pamięci. Jest to flaga -i, która przydziela pamięć buforową w kontenerze dla strumienia stdin, stąd opis „Zachowaj STDIN otwarty, nawet jeśli nie jest podłączony”, gdy przekazane jest -i, pamięć jest przydzielana dla stdin niezależnie od flag załączania. Bez tej przydzielonej pamięci odczyty stdin są puste / eof. Musisz także dodać „-a = stdout”, aby zobaczyć odpowiedź z polecenia cat, na przykład: „docker run -i -a = stdin -a = stdout alpine cat” ... oczywiście nie ma takiej potrzeby, możesz to zrobić po prostu uruchom „docker run -i alpine cat”.
David D

71

Według -twyszukiwarki Google argument NIE jest dobrze udokumentowany ani często wymieniany przez wiele osób.

Nie pojawia się nawet, gdy wyświetlasz listę (co powinno być) wszystkich argumentów klienta dokera, pisząc dockerw wierszu polecenia Bash (w najnowszej wersji 1.8.1).

W rzeczywistości, jeśli spróbujesz uzyskać konkretną pomoc na temat tego argumentu, pisząc, docker -t --helpjeśli daje niesamowicie niejasną odpowiedź:

flaga podana, ale nie zdefiniowana: -t

Nie możesz więc winić za to, że pomyliłeś się co do tego argumentu!

W dokumentacji online Dockera znajduje się wzmianka, że ​​jest to „Przydziel pseudo-tty” i jest często używane z -i :

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

Widziałem go w dokumentacji wspaniałego jwilder/nginx-proxykontenera dokerów w następujący sposób:

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

W tym przypadku wysyła dane wyjściowe do „wirtualnego” tty (wiersz poleceń / terminal Bash) w tym kontenerze dokera. Następnie możesz wyświetlić ten wynik, uruchamiając polecenie dokera, docker logs CONTAINERgdzie CONTAINERjest pierwsza para znaków identyfikatora tego kontenera. Ten identyfikator KONTENERA można znaleźć, piszącdocker ps -a

Widziałem ten -targument krótko wspomniany w poniższym linku, w którym jest on podany

-tI -iflagi przeznaczyć pseudo-tty i zachować stdin otwarty nawet jeśli nie dołączone. Umożliwi to używanie kontenera jak tradycyjnej maszyny wirtualnej, dopóki uruchomiony jest monit bash.

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

Mam nadzieję, że to pomoże! Nie jestem pewien, dlaczego nie jest to często udokumentowane lub używane. Być może jest to eksperymentalne i zostanie zaimplementowane jako udokumentowana funkcja w nadchodzących wersjach.


21
Dokumentacja pokazuje docker run --help, a nie docker -t --help: -t, --tty=false Allocate a pseudo-TTY
bskaggs

5

Co wiem o -t co następuje:

docker exec -ti CONTAINER bash- pozwala mi „zalogować się” w kontenerze. Czuje się jak ssh -ing (nie jest).

Problem polegał na tym, że chciałem przywrócić bazę danych.

Zwykle takdocker exec -ti mysql.5.7 mysql - tutaj polecenie mysql w kontenerze i otrzymuję interaktywny terminal.

Dodałem <dump.sqldo poprzedniego polecenia, aby móc przywrócić bazę danych. Ale nie udało sięcannot enable tty mode on non tty input .

Usuwanie -tpomógł. Nadal nie rozumiem, dlaczego:

docker exec -i mysql.5.7 mysql < dump.sql

Ostatni działa. Mam nadzieję, że to pomaga ludziom.


Czy mogę uruchomić tty w oknie dokowanym? Mam aplikację, która przestaje działać, ale nie uruchamiam dokera -t, ale nie mogę modyfikować komendy uruchamiania dokera w środowisku produkcyjnym. Muszę więc sprawić, by aplikacja zaczęła myśleć -t.
mvorisek

1

W Linuksie po uruchomieniu polecenia potrzebny jest terminal (tty), aby go wykonać.

Więc jeśli chcesz połączyć się z dokerem (lub uruchomić polecenie w kontenerze dokera), musisz podać opcję -t, która bierze pod uwagę terminal wewnątrz kontenera dokera.


0

Każdy proces ma trzy strumienie danych, tj STDIN/ STDOUT/ STDERR. Gdy proces działa w kontenerze, domyślnie terminal jest połączony ze strumieniem STDOUT procesu działającego w kontenerze. Dlatego wszystkie strumienie wyjściowe będą widoczne podczas uruchamiania docker runpolecenia w terminalu. Ale jeśli chcesz wprowadzić dane wejściowe do uruchomionego procesu w kontenerze, musisz połączyć się z kanałem STDIN procesu, który nie jest domyślnie i jest wykonywany zdocker run -i polecenia.

-t służy do interaktywnych / sformatowanych operacji wprowadzania.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.