Запутался в опции Docker -t для выделения псевдо-TTY


209

Что именно делает эта опция? Я много читал на TTY и все еще в замешательстве. Я играл с отсутствием -tи просто, -iи кажется, что программы, которые ожидают пользовательского ввода, выдают ошибку без -t. Почему важно включить псевдо-TTY?

Ответы:


225

-tВариант идет к тому, как Unix / Linux обрабатывает терминальный доступ. В прошлом терминал был жестким соединением, позже модемным соединением. У них были драйверы для физических устройств (они были настоящими частями оборудования). Как только обобщенные сети начали использоваться, был разработан драйвер псевдо-терминала. Это потому, что это создает разделение между пониманием того, какие возможности терминала можно использовать, без необходимости записывать их непосредственно в вашу программу (читайте справочные страницы stty, curses).

Итак, с этим в качестве фона, запустите контейнер без параметров, и по умолчанию у вас есть поток stdout (так docker run | <cmd>работает); запустить с -i, и вы получите поток stdin (так <cmd> | docker run -iработает); используйте -t, как правило, в комбинации, -itи у вас есть добавленный драйвер терминала, который, если вы взаимодействуете с процессом, скорее всего, то, что вы хотите. Это в основном делает начало контейнера похожим на сеанс терминального соединения.


7
Это должен быть главный ответ. Хотя он не самый технический, он объясняет фундаментальное поведение -itфлагов.
Крис Хайра

1
Согласитесь с Крисом. Я прочитал другие ответы и все еще был в замешательстве. Этот ответ проясняет это.
Бен Ли

4
Да, возможно, стоит упомянуть, что само слово «TTY» является аббревиатурой от слова «teletypewriter» (AKA «teleprinter»), которое представляет собой имя устройства, позволяющее набирать текст и отправлять его одновременно - как телефон для текста ;-) Попробуйте, docker run -i ubuntuи docker run -it ubuntuвы увидите разницу сразу. «-i» позволяет заставить контейнер ожидать взаимодействия с хостом, но фактическое взаимодействие с консолью (терминалом) возможно после того, как вы «выделите tty драйвер» с флагом «-t».
Зегар

Могу ли я запустить tty в докере? У меня есть приложение, которое перестает работать -t, но я не запускаю докер , но не могу изменить команду запуска докера в рабочей среде. Поэтому мне нужно заставить приложение думать, что оно было начато -t.
Мворисек

98

Поздний ответ, но может помочь кому-то

docker run/exec -iсоединит STDIN команды внутри контейнера с STDIN docker run/execсамого.

Так

  • docker run -i alpine catвыдает пустую строку в ожидании ввода. Типа "привет", вы получаете эхо "привет". Контейнер не выйдет, пока вы не отправите CTRL+, Dпотому что основной процесс catожидает ввода от бесконечного потока, который является входом терминала для docker run.
  • С другой стороны echo "hello" | docker run -i alpine cat, напечатает «привет» и сразу же catзавершит работу, потому что замечает, что поток ввода закончился и завершает себя.

Если вы попытаетесь docker psпосле выхода из любого из вышеперечисленных, вы не найдете никаких работающих контейнеров. В обоих случаях catсамо завершение работы завершилось, поэтому docker завершил работу контейнера.

Теперь для "-t" это говорит главному процессу внутри докера, что его вход является терминальным устройством.

Так

  • docker run -t alpine catвыдаст пустую строку, но если вы попытаетесь напечатать "привет", вы не получите никакого эха. Это потому, что хотя catон подключен к входу терминала, этот вход не подключен к вашему входу. «Привет», который вы ввели, не дошел до ввода cat. catждет ввода, который никогда не поступит.
  • echo "hello" | docker run -t alpine catтакже даст вам пустую строку и не выйдет из контейнера на CTRL- Dно вы не получите эхо "привет", потому что вы не прошли-i

Если вы отправите CTRL+ C, вы вернете свою оболочку, но если вы попробуете docker psсейчас, вы увидите, что catконтейнер все еще работает. Это потому, что catвсе еще ожидает входной поток, который никогда не был закрыт. Я не нашел никакого полезного использования для -tодиночества, не будучи объединенным с -i.

Теперь -itвместе. Это говорит cat, что его вход является терминалом, и в то же время подключите этот терминал к входу docker runкоторого является терминалом. docker run/execпрежде чем передать его, убедитесь, что его собственный ввод является tty cat. Вот почему вы получите, input device is not a TTYесли попытаетесь, echo "hello" | docker run -it alpine catпотому что в этом случае вход docker runсам по себе является каналом от предыдущего эха, а не терминалом, где docker runвыполняется

Наконец, зачем вам нужно проходить, -tесли у вас -iбудет возможность подключить ваш вход к catвходу? Это потому, что команды обрабатывают ввод по-разному, если это терминал. Это также лучше всего иллюстрируется на примере

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -u root -pдаст вам запрос пароля. Если вы введете пароль, символы будут напечатаны визуально.
  • docker run -i alpine shдаст вам пустую строку. Если вы наберете команду, как lsвы получите вывод, но вы не получите приглашение или цветной вывод.

В последних двух случаях вы получаете это поведение, потому mysqlчто вы shellне обрабатываете ввод как tty и, следовательно, не используете специфическое для tty поведение, такое как маскирование ввода или окрашивание вывода.


6
Лучший ответ здесь, который действительно заставляет меня понять, что именно -tи -iварианты делают!
Руслан Стельмаченко

1
Фантастический ответ, который предвосхищал все
Джеймс Мачин

@ Ахмед Гоним, Очень хорошие ответы. Спасибо. Но насчет «Это потому, что команды обрабатывают ввод по-разному, если это терминал», я думаю, что это опечатка, верно? Должно быть «Это потому, что команды обрабатывают ввод по-разному, если это не терминал», верно?
tuq

@ Ахмед Гоним. Кристально чистый. Но как насчет запуска docker -a = stdin alpine cat?
HKIT

1
@HKIIT "-a = stdin" присоединяет поток stdin к контейнеру, но без выделения памяти. Это флаг -i, который выделяет буферную память в контейнере для потока stdin, поэтому в описании «Держите STDIN открытым, даже если он не подключен», когда передается -i, память выделяется для stdin независимо от флагов вложений. Без этой выделенной памяти чтения в stdin пусты / eof. Также вам нужно включить «-a = stdout», чтобы увидеть ответ от команды cat, например: «docker run -i -a = stdin -a = stdout alpine cat» ... конечно, нет необходимости делать это, вы можете просто запустите "Docker Run -i Alpine Cat".
Дэвид Д

71

-tАргумент не документирован хорошо, или упоминается многими людьми , часто, по данным поиска Google.

Он даже не отображается, когда вы выводите список (что должно быть) всех аргументов докер-клиента, набирая dockerв приглашении Bash (с последней версией 1.8.1).

На самом деле, если вы попытаетесь получить конкретную помощь по этому аргументу, набрав docker -t --helpif , вы получите удивительно смутный ответ:

флаг указан, но не определен: -t

Таким образом, вы не можете быть обвинены в том, что запутались в этом аргументе!

В онлайн-документации Docker есть упоминание о том, что оно «выделяет псевдо-tty» и часто используется с -i:

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

Я видел, что он использовался в документации для потрясающего jwilder/nginx-proxyдок-контейнера следующим образом:

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

В этом случае он отправляет выходные данные в «virtual» tty (командная строка / терминал Bash) в этом контейнере Docker. Затем вы можете увидеть эти выходные данные, выполнив команду docker docker logs CONTAINERгде CONTAINERпервая пара символов идентификатора этого контейнера. Этот идентификатор контейнера можно найти, набравdocker ps -a

Я видел этот -tаргумент кратко упоминается в следующей ссылке, где он говорит

-tИ -iфлаги выделить псевдо-терминал и держать стандартный ввод открытым , даже если не прилагается. Это позволит вам использовать контейнер как традиционную виртуальную машину, пока работает приглашение bash.

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

Надеюсь, это поможет! Я не уверен, почему это не задокументировано или не используется много. Возможно, это экспериментально и будет реализовано как документированная функция в следующих версиях.


21
Документация показывается docker run --help, а не docker -t --help: -t, --tty=false Allocate a pseudo-TTY"
bskaggs

5

Что я знаю о -tследующем:

docker exec -ti CONTAINER bash- позволяет мне «войти» в контейнер. Это похоже на ssh-ing (это не так).

Но беда была, когда я захотел восстановить базу данных.

Обычно я делаю docker exec -ti mysql.5.7 mysql- здесь я выполняю команду mysql в контейнере и получаю интерактивный терминал.

Я добавил <dump.sqlк предыдущей команде, чтобы я мог восстановить БД. Но это не удалось с cannot enable tty mode on non tty input.

Удаление -tпомогло. Все еще не понимаю, почему:

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

Последний работает. Надеюсь, что это помогает людям.


Могу ли я запустить tty в докере? У меня есть приложение, которое перестает работать -t, но я не запускаю докер , но не могу изменить команду запуска докера в рабочей среде. Поэтому мне нужно заставить приложение думать, что оно было начато -t.
Мворисек

1

В Linux, когда вы запускаете команду, вам нужен терминал (tty) для ее выполнения.

Поэтому, когда вы хотите подключиться к Docker (или запустить команду в Docker-контейнере), вы должны указать параметр -t, который учитывает наличие терминала в Docker-контейнере.


0

Каждый процесс имеет три потоки данных ИЭ STDIN/ STDOUT/ STDERR. Когда процесс выполняется в контейнере, по умолчанию терминал связан с потоком STDOUT процесса, выполняющегося в контейнере. Следовательно, все выходные потоки будут видны при запуске docker runкоманды в терминале. Но если вы хотите обеспечить ввод для запущенного процесса в контейнере, то вам нужно соединиться с каналом STDIN процесса, который не является по умолчанию и выполняется docker run -iкомандой.

-t используется для интерактивных / форматированных операций ввода.


-3

-itИнструктирует DOCKER выделить псевдо-TTY , соединенную с стандартным вводом контейнера, создавая интерактивную оболочку Баша в контейнере.

--interactive, -i falseKeep STDIN открыть , даже если не прилагается

--tty, -t false Выделяют псевдо-TTY

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.