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

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

Вот команда, которая работает:

$ echo 'hi there' | docker run -i ubuntu cat
hi there

Это команда, которая отвечает сообщением об ошибке:

$ echo 'hi there' | docker run -it ubuntu cat
the input device is not a TTY

Я хотел бы выяснить, что именно здесь происходит. А не просто "удали -t и все будет исправлено".

Я знаю, что docker runопция -tозначает «Выделить псевдо-TTY», и я читалисторические обзоры того, что означает TTY, но это не помогло мне понять, какой именно договор здесь нарушен.

решение1

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

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

Так

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

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

Теперь о «-t», который сообщает основному процессу внутри Docker, что его входные данные — это терминальное устройство.

Так

  • docker run -t alpine catдаст вам пустую строку, но если вы попытаетесь ввести "hello", вы не получите никакого эха. Это потому, что while catподключен к терминальному входу, этот вход не подключен к вашему входу. "hello", который вы набрали, не достиг входа cat. catожидает ввода, который никогда не поступит.
  • echo "hello" | docker run -t alpine catтакже выдаст вам пустую строку и не выйдет из контейнера по CTRL-D, но вы не получите echo "hello", потому что вы не передали-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выполняется

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

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

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

решение2

Этот ответпомогло мне осознать:

  • по умолчанию (без опций neither -i) -tконтейнер Docker отправляет свой вывод только в STDOUT,
  • с -iопцией идет подключение к STDIN,
  • -tопция подключает драйвер интерфейса терминала, который работает поверх STDIN/STDOUT. И когда подключается драйвер терминала, связь с контейнером должна соответствоватьпротокол терминального интерфейса. Игра на струне не делает этого.

решение3

Tty указывает на то, что у вас есть терминал, то есть то, что предоставляется xterm или одним из многих интерфейсов командной строки Linux. Ему нужна клавиатура и связанный с ним интерфейс текстового вывода. Типичные причины, по которым это нужно, — поддержка цветного текстового вывода, обработка различных комбинаций клавиш (например, клавиш со стрелками) и возможность перемещать курсор по экрану.

Когда вы передаете команду в docker, как echoпоказано в вашем примере, этот канал является входом, и у этого канала нет интерфейса tty, это просто поток текста. Попытка создать tty с этим потерпит неудачу, как указано в сообщении об ошибке.

Связанный контент