Что именно означает "устройство ввода не является TTY" в выводе "docker run"?

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

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, что его ввод является терминальным устройством.

Так

  • 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 сам по себе является каналом из предыдущего echo, а не терминалом, где 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 поведение, такое как маскирование входных данных или раскрашивание выходных данных.