Что именно делает этот вариант? Я много читал о TTY и все еще смущен. Я играл, не имея -t
и просто -i
, и кажется, что программы, ожидающие ввода пользователем, вызывают ошибку без -t
. Почему важно, чтобы псевдо-TTY был включен?
Смутно о выборе Docker -t для выделения псевдотематики
Ответ 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