Плутати про варіант Docker -t для виділення псевдо-TTY


206

Що саме робить цей варіант? Я багато читав на TTY і все ще розгублений. Я розігрувався з тим, що не маю -tсправедливих -iі, схоже, програм, які очікують, що користувальницькі дані вводять помилку без -t. Чому важливо включити псевдо-TTY?

Відповіді:


223

Ця -tопція стосується того, як Unix / Linux обробляє термінальний доступ. У минулому термінал являв собою жорстке з'єднання, пізніше - модемне з'єднання. У них були драйвери фізичних пристроїв (це були справжні предмети обладнання). Після введення узагальнених мереж було розроблено драйвер псевдотерміналу. Це відбувається тому, що це створює розрив між розумінням того, які можливості терміналу можна використовувати без необхідності записувати їх у вашу програму (читайте підручні сторінки на stty, curses).

Отже, використовуючи це як фон, запустіть контейнер без параметрів і за замовчуванням у вас є потік stdout (так docker run | <cmd>працює); запустіть з -i, і ви отримаєте stdin потік (так <cmd> | docker run -iпрацює); використання -t, як правило, у поєднанні, -itі у вас додається драйвер терміналу, який, якщо ви взаємодієте з процесом, швидше за все, що вам потрібно. Це, в основному, робить запуск контейнера схожим на сеанс з'єднання з терміналом.


7
Це має бути головна відповідь. Незважаючи на те, що це не самий технічний, він пояснює принципову поведінку -itпрапорів.
Kris Khaira

1
Погодьтеся з Крисом. Я прочитав інші відповіді і все ще був абсолютно розгублений. Ця відповідь це очищає.
Бен Лі

3
Так, варто, мабуть, згадати, що сам "TTY" - це абревіатура, що походить від слова "телетайпер" (телеканал "AKA"), яке було назвою пристрою, що дозволяє вводити текст і надсилати його в той же час - як телефон для тексту ;-) Спробуйте, docker run -i ubuntuі docker run -it ubuntuви побачите різницю відразу. "-i" дозволяє змусити контейнер чекати взаємодії з хостом, але реальна взаємодія з консолі (терміналу) можлива після того, як ви "виділите драйвер tty" з прапором "-t".
Зегар

Чи можна запустити tty в докер? У мене є програма, яка перестає працювати, я не запускаю докер -t, але не можу змінити команду запуску докера у виробництві. Тому мені потрібно змусити додаток думати, що це було запущено з -t.
mvorisek

97

Пізня відповідь, але може комусь допомогти

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сам припинився, таким чином докер припинив контейнер.

Тепер для "-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разом. Це говорить кішці, що її вхід є терміналом і одночасно підключають цей термінал, на вході docker runякого є термінал. docker run/execпереконайтесь, що його власний вклад є насправді десятки перед тим, як передавати його 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 -u root -pнадасть вам запит на пароль. Якщо ви введете пароль, символи друкуються помітно.
  • docker run -i alpine shдасть вам порожній рядок. Якщо ви введете команду, як lsви отримаєте вихід, але ви не отримаєте підказку або кольоровий вихід.

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


6
Найкраща відповідь тут, яка насправді змушує мене зрозуміти, що саме -tі -iваріанти роблять!
Руслан

1
Фантастична відповідь, яка передбачала кожне моє запитання
Джеймс Макін

@Ahmed Ghonim, Дуже хороші відповіді. Дякую. Але щодо "Це тому, що команди по-різному ставляться до вводу, якщо це термінал", я вважаю, що це помилка, правда? Це має бути "Це тому, що команди по-різному ставляться до вводу, якщо це не термінал", правда?
tuq

@Ahmed Ghonim. Кристально чистий. А як же докер бігати -a = stdin альпійський кіт?
HKIT

1
@HKIIT "-a = stdin" додає потік stdin до контейнера, але без розподілу пам'яті. Це прапор -i, який виділяє буферну пам'ять у контейнері для потоку stdin, отже, опис "Тримайте STDIN відкритим, навіть якщо він не додається", коли -i передається пам'ять для stdin незалежно від прапорів вкладення. Без цього виділеної пам'яті читання до stdin є порожніми / eof. Також вам потрібно включити "-a = stdout", щоб побачити відповідь команди cat, наприклад: "docker run -i -a = stdin -a = stdout alpine cat" ... звичайно, це не потрібно робити, ви можете просто запустіть "docker run - я альпійська кішка".
Девід Д

71

-tАргументом документований добре, або згадується багатьма людьми , часто, за даними пошуку Google.

Він навіть не відображається, коли ви відображаєте список (що має бути) всіх аргументів клієнтського докера, ввівши dockerпідказку Bash (з останньою версією 1.8.1).

Насправді, якщо ви спробуєте отримати конкретну допомогу щодо цього аргументу, ввівши docker -t --help чи дає це дивовижно невиразний відповідь:

прапор надається, але не визначено: -t

Отже, вас не можна звинувачувати в тому, що ви плутаєте цей аргумент!

У онлайн-документації Docker є згадка, яка говорить про те, що це "Виділити псевдо-tty" і часто використовується з -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 logs CONTAINERдеCONTAINER є перша пара символів ідентифікатора цього контейнера. Цей ідентифікатор CONTAINER можна знайти, ввівшиdocker ps -a

Цей -tаргумент я коротко бачив у наступному посиланні, де він говорить

-tІ -iпрапори виділити псевдо-термінал і тримати стандартний ввід відкритим , навіть якщо не додається. Це дозволить вам використовувати контейнер, як традиційний VM, поки запущено запит bash.

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

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


21
Документація відображається на docker run --help, а не docker -t --help: -t, --tty=false Allocate a pseudo-TTY"
bskaggs

5

Що я знаю про -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

Останній працює. Сподіваюсь, це допомагає людям.


Чи можна запустити tty в докер? У мене є програма, яка перестає працювати, я не запускаю докер -t, але не можу змінити команду запуску докера у виробництві. Тому мені потрібно змусити додаток думати, що це було запущено з -t.
mvorisek

1

У Linux для запуску команди вам потрібен термінал (tty) для його виконання.

Отже, коли ви хочете підключитися до docker (або запустити команду в контейнері docker), ви повинні надати опцію -t, яка бере на розгляд термінал всередині контейнера докера.


0

Кожен процес має три потоки даних, тобто STDIN/ STDOUT/ STDERR. Коли процес працює в контейнері, термінал за замовчуванням підключається до потоку STDOUT процесу, що працює в контейнері. Отже, всі вихідні потоки будуть видні під час виконання docker runкоманди в терміналі. Але якщо ви хочете надати вхід до запущеного процесу в контейнері, вам доведеться підключитися до каналу STDIN процесу, який не є за замовчуванням і виконується docker run -iкомандою.

-t використовується для інтерактивних / відформатованих операцій введення.


-3

-itІнструктує DOCKER виділити псевдо-TTY , з'єднану з стандартним вводом контейнера, створюючи інтерактивну оболонку Баша в контейнері.

--interactive, -i falseТримайте STDIN відкритим, навіть якщо він не встановлений

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.