Что именно делает этот вариант? Я много читал о 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