Confundido acerca de la opción Docker -t para asignar un pseudo-TTY


208

¿Qué hace exactamente esta opción? He estado leyendo mucho en TTY y todavía estoy confundido. Jugué con no tener el -ty justo -iy parece que los programas que esperan la entrada del usuario arrojan un error sin el -t. ¿Por qué es importante habilitar pseudo-TTY?

Respuestas:


224

La -topción va a cómo Unix / Linux maneja el acceso a la terminal. En el pasado, un terminal era una conexión de línea dura, luego una conexión basada en módem. Estos tenían controladores de dispositivos físicos (eran piezas reales de equipo). Una vez que las redes generalizadas entraron en uso, se desarrolló un controlador de pseudo-terminal. Esto es debido a que crea una separación entre la comprensión de lo que las capacidades del terminal se pueden utilizar sin necesidad de escribirlo en su programa directamente (leer páginas de manual en stty, curses).

Entonces, con eso como fondo, ejecute un contenedor sin opciones y, de forma predeterminada, tiene una secuencia estándar (así docker run | <cmd>funciona); ejecuta con -i, y obtienes flujo stdin agregado (así <cmd> | docker run -ifunciona); use -t, generalmente en la combinación -ity tiene un controlador de terminal agregado, que si está interactuando con el proceso es probablemente lo que desea. Básicamente hace que el inicio del contenedor parezca una sesión de conexión de terminal.


77
Esta debería ser la mejor respuesta. Si bien no es el más técnico aquí, explica el comportamiento fundamental de las -itbanderas.
Kris Khaira

1
De acuerdo con Kris. Leí las otras respuestas y todavía estaba totalmente confundido. Esta respuesta lo aclara.
Ben Lee

44
Sí, quizás valga la pena mencionar que "TTY" en sí es un acrónimo que proviene de la palabra "teletipo" (AKA "teleimpresora") que era un nombre de dispositivo que le permite escribir texto y enviarlo al mismo tiempo, como un teléfono para texto ;-) Intenta docker run -i ubuntuy docker run -it ubuntuverás la diferencia inmediatamente. "-i" le permite hacer que el contenedor espere la interacción del host, pero la interacción real desde la consola (terminal) es posible después de "asignar el controlador tty" con la marca "-t".
Zegar

¿Puedo iniciar tty dentro de la ventana acoplable? Tengo alguna aplicación que deja de funcionar con la que no ejecuto la ventana acoplable -t, pero no puedo modificar el comando de inicio de la ventana acoplable en producción. Así que necesito hacer que la aplicación piense que se inició -t.
mvorisek

98

Respuesta tardía, pero podría ayudar a alguien

docker run/exec -iconectará el STDIN del comando dentro del contenedor al STDIN del docker run/execmismo.

Entonces

  • docker run -i alpine catle da una línea vacía en espera de entrada. Escriba "hola" obtendrá un eco "hola". El contenedor no saldrá hasta que envíe CTRL+ Dporque el proceso principal catestá esperando la entrada del flujo infinito que es la entrada terminal del docker run.
  • Por otro lado echo "hello" | docker run -i alpine cat, imprimirá "hola" y saldrá inmediatamente porque se catda cuenta de que la secuencia de entrada ha finalizado y termina por sí misma.

Si intenta docker psdespués de salir de cualquiera de los anteriores, no encontrará ningún contenedor en ejecución. En ambos casos, el catmismo ha terminado, por lo tanto, la ventana acoplable ha terminado el contenedor.

Ahora para "-t", esto le dice al proceso principal dentro de Docker que su entrada es un dispositivo terminal.

Entonces

  • docker run -t alpine catle dará una línea vacía, pero si intenta escribir "hola", no obtendrá ningún eco. Esto se debe a que mientras catestá conectado a una entrada de terminal, esta entrada no está conectada a su entrada. El "hola" que escribió no alcanzó la entrada de cat. catestá esperando una entrada que nunca llega.
  • echo "hello" | docker run -t alpine cattambién le dará una línea vacía y no saldrá del contenedor CTRL, Dpero no obtendrá un eco "hola" porque no pasó-i

Si envía CTRL+ C, recupera su shell, pero si lo intenta docker psahora, verá que el catcontenedor sigue ejecutándose. Esto se debe a catque todavía está esperando una secuencia de entrada que nunca se cerró. No he encontrado ningún uso útil para el -tsolo sin ser combinado con -i.

Ahora, para -itjuntos. Esto le dice a cat que su entrada es una terminal y al mismo tiempo conecte esta terminal a la entrada de la docker runcual es una terminal. docker run/execse asegurará de que su propia entrada sea de hecho un tty antes de pasarla cat. Es por eso que obtendrá un input device is not a TTYsi lo intenta echo "hello" | docker run -it alpine catporque en este caso, la entrada de docker runsí mismo es la tubería del eco anterior y no el terminal donde docker runse ejecuta

Finalmente, ¿por qué necesitaría pasar -tsi -ihará el truco de conectar su entrada a catla entrada de? Esto se debe a que los comandos tratan la entrada de manera diferente si es una terminal. Esto también se ilustra mejor con un ejemplo.

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -u root -ple dará un mensaje de contraseña. Si escribe la contraseña, los caracteres se imprimen visiblemente.
  • docker run -i alpine shte dará una línea vacía. Si escribe un comando como lsse obtiene una salida, pero no obtendrá un mensaje o una salida de color.

En los últimos dos casos, obtiene este comportamiento porque mysql, además de shellno tratar la entrada como un tty, no utilizó el comportamiento específico de tty como enmascarar la entrada o colorear la salida.


66
¡La mejor respuesta aquí que realmente me hace entender exactamente qué hacen -ty -iqué opciones hacen!
Ruslan Stelmachenko

1
Fantástica respuesta que anticipó cada pregunta que tenía
James Machin

@ Ahmed Ghonim, Muy buenas respuestas. Gracias. Pero sobre "Esto se debe a que los comandos tratan la entrada de manera diferente si es una terminal", creo que es un error, ¿verdad? Debe ser "Esto se debe a los comandos tratan a la entrada de manera diferente si es no un terminal", ¿verdad?
tuq

@Ahmed Ghonim. Claro como el cristal. Pero ¿qué pasa con Docker Run -a = gato alpino stdin?
HKIT

1
@HKIIT "-a = stdin" adjunta el flujo de stdin al contenedor pero sin una asignación de memoria. Es el indicador -i el que asigna la memoria del búfer en el contenedor para la secuencia stdin, de ahí la descripción "Mantener STDIN abierto incluso si no está adjunto", cuando se pasa -i, la memoria se asigna para stdin independientemente de los indicadores adjuntos. Sin esto, las lecturas de memoria asignadas a stdin están vacías / eof. También debe incluir "-a = stdout" para ver la respuesta del comando cat, por ejemplo: "docker run -i -a = stdin -a = stdout alpine cat" ... por supuesto, no hay necesidad de hacerlo. simplemente ejecute "docker run -i alpine cat".
David D

71

El -targumento NO está bien documentado, o muchas personas lo mencionan a menudo, según una búsqueda en Google.

Ni siquiera aparece cuando muestra una lista de (lo que debería ser) todos los argumentos del cliente acoplable escribiendo dockeren el indicador Bash (con la última versión de 1.8.1).

De hecho, si intenta obtener ayuda específica sobre este argumento escribiendo docker -t --helpif da esta respuesta increíblemente vaga:

Indicador proporcionado pero no definido: -t

¡Entonces, no se te puede culpar por estar confundido sobre este argumento!

Hay una mención en la documentación en línea de Docker que dice que es "Asignar un pseudo-tty" y a menudo se usa con -i:

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

Vi que se usaba en la documentación del excelente jwilder/nginx-proxycontenedor acoplable de la siguiente manera:

docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx

En este caso, lo que hace es enviar la salida al tty 'virtual' (símbolo del sistema Bash / terminal) dentro de este contenedor acoplable. Luego puede ver esta salida ejecutando el comando docker docker logs CONTAINERdonde se CONTAINERencuentran los primeros dos caracteres de la ID de este contenedor. Esta ID DE CONTENEDOR se puede encontrar escribiendodocker ps -a

He visto este -targumento mencionado brevemente en el siguiente enlace, donde dice

Las banderas -ty -iasignan un pseudo-tty y mantienen abierto el stdin incluso si no está adjunto. Esto le permitirá usar el contenedor como una VM tradicional siempre que se ejecute el indicador bash.

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

¡Espero que esto ayude! No estoy seguro de por qué esto no está documentado o se usa mucho. Tal vez sea experimental y se implementará como una característica documentada en las próximas versiones.


21
La documentación aparece para docker run --help, no docker -t --help: -t, --tty=false Allocate a pseudo-TTY"
bskaggs

5

Lo que sé sobre esto -tes lo siguiente:

docker exec -ti CONTAINER bash- me permite "iniciar sesión" en el contenedor. Se siente como una mierda (no lo es).

Pero el problema era cuando quería restaurar una base de datos.

Normalmente lo hago docker exec -ti mysql.5.7 mysql: aquí ejecuto el comando mysql en el contenedor y obtengo un terminal interactivo.

Agregué <dump.sqlel comando anterior para poder restaurar un db. Pero falló con cannot enable tty mode on non tty input.

Eliminando los -tayudados. Aún no entiendo por qué:

docker exec -i mysql.5.7 mysql < dump.sql

El último funciona. Espero que esto ayude a la gente.


¿Puedo iniciar tty dentro de la ventana acoplable? Tengo alguna aplicación que deja de funcionar con la que no ejecuto la ventana acoplable -t, pero no puedo modificar el comando de inicio de la ventana acoplable en producción. Así que necesito hacer que la aplicación piense que se inició -t.
mvorisek

1

En Linux cuando ejecuta un comando, necesita un terminal (tty) para ejecutarlo.

Entonces, cuando desee conectarse a la ventana acoplable (o ejecutar el comando en el contenedor de la ventana acoplable), debe proporcionar la opción -t que toma en consideración la terminal dentro del contenedor de la ventana acoplable.


0

Cada proceso tiene tres flujos de datos, es decir STDIN/ STDOUT/ STDERR. Cuando un proceso se ejecuta en un contenedor, por defecto el terminal está conectado con la secuencia STDOUT del proceso que se ejecuta en el contenedor. Por lo tanto, todos los flujos de salida serán visibles mientras se ejecuta el docker runcomando en la terminal. Pero si desea proporcionar información para el proceso en ejecución en el contenedor, entonces debe conectarse con el canal STDIN del proceso, que no es por defecto y se hace con el docker run -icomando.

-t se utiliza para operaciones de entrada interactivas / formateadas.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.