Подтвердить что ты не робот

Смутно о выборе Docker -t для выделения псевдотематики

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

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

В онлайн-документации Docker есть упоминание о том, что оно "выделяет псевдо -t" и часто используется с -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

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

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

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

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

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

Ответ 3

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

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

Так

  • docker run -i alpine cat дает пустую строку в ожидании ввода. Типа "привет", вы получаете эхо "привет". Контейнер не выйдет, пока вы не отправите CTRL + D, потому что основной процесс cat ожидает ввода из бесконечного потока, который является терминальным входом docker run.
  • С другой стороны, echo "hello" | docker -i run alpine cat выведет "hello" и немедленно выйдет, потому что 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 -uroot -p выдаст вам запрос пароля. Если вы введете пароль, символы будут напечатаны видимым образом.
  • docker run -i alpine sh даст вам пустую строку. Если вы наберете команду типа ls, вы получите вывод, но вы не получите быстрый или цветной вывод.

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

Ответ 4

То, что я знаю о -t, следующее:

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

Но проблема была в том, что я хотел восстановить базу данных.

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

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

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

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

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

Ответ 5

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

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

Ответ 6

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

--interactive, -i false Держите STDIN открытым, даже если он не подключен

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

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