¿Qué significa exactamente "el dispositivo de entrada no es un TTY "en la salida" ejecutar docker"?

Este es un comando que funciona:

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

Este es un comando que responde con un mensaje de error:

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

Me gustaría averiguar exactamente qué sucede aquí. No solo "quita-t y se arreglará".

Yo sé eso docker run's -t la opción significa "Asignar un pseudo-TTY" , y he leído descripciones históricas de lo que significa TTY, pero no me ayudó a entender qué tipo de contrato se viola aquí.

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

docker run/exec -i conectará el STDIN del comando dentro del contenedor al STDIN del docker run/exec mismo.

Tan

  • docker run -i alpine cat le da una línea vacía en espera de entrada. Tipo "hola" hay un eco "hola". El contenedor no saldrá hasta que envíe CTRL + D porque el proceso principal cat está esperando la entrada del flujo infinito que es la entrada del terminal del docker run.
  • Por otro lado echo "hello" | docker run -i alpine cat imprimirá & quot; hola" y saldrá inmediatamente porque cat nota que el flujo de entrada ha finalizado y finaliza por sí mismo.

Si lo intentas docker ps después de salir de cualquiera de los anteriores, no encontrará ningún contenedor en ejecución. En ambos casos, cat ha terminado, por lo que docker ha terminado el contenedor.

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

Tan

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

Si envías CTRL + C, recuperas tu shell, pero si lo intentas docker ps ahora, ves el cat el contenedor sigue funcionando. Esto se debe a que cat todavía está esperando en un flujo de entrada que nunca se cerró. No he encontrado ningún uso útil para el -t solo sin estar combinado con -i.

Ahora, para -it junto. Esto le dice a cat que su entrada es un terminal y al mismo tiempo conecta este terminal a la entrada de docker run que es una terminal. docker run/exec se asegurará de que su propia entrada sea de hecho un tty antes de pasarla a cat. Es por eso que obtendrá un input device is not a TTY si lo intentas echo "hello" | docker run -it alpine cat porque en este caso, la entrada de docker run en sí mismo es la tubería del eco anterior y no el terminal donde docker run se ejecuta

Finalmente, ¿por qué necesitarías aprobar -t si -i hará el truco de conectar su entrada a cat¿la entrada de s? Esto se debe a que los comandos tratan la entrada de manera diferente si es un terminal. Esto también se ilustra mejor con un ejemplo

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p le pedirá una contraseña. Si escribe la contraseña, los caracteres se imprimen de forma visible.
  • docker run -i alpine sh te dará una línea vacía. Si escribe un comando como ls obtiene una salida, pero no obtendrá una salida rápida o coloreada.

En los dos últimos casos, obtienes este comportamiento porque mysql así como shell no trataban la entrada como un tty y, por lo tanto, no usaban un comportamiento específico de tty como enmascarar la entrada o colorear la salida.

Esta respuesta me ayudó a envolver mi cabeza:

  • por defecto (sin ninguno de los dos -i ni -t opciones) un contenedor Docker solo envía su salida a Stdout,
  • con -i opción de conexión a STDIN,
  • -t la opción extrae un controlador de interfaz de terminal, que funciona sobre STDIN / STDOUT. Y cuando se tira de un controlador de terminal, la comunicación con un contenedor debe ajustarse al protocolo de interfaz de terminal. La tubería de una cuerda no lo hace.

Un tty indica que tiene un terminal, algo que sería proporcionado por xterm o una de las muchas interfaces de línea de comandos de Linux. Necesita un teclado y una interfaz de salida de texto asociados. Las razones típicas para querer esto son el soporte de salida de texto en color, el manejo de varias combinaciones de teclas (como las teclas de flecha) y la capacidad de mover el cursor por la pantalla.

Cuando canalizas un comando en docker como tu echo el ejemplo muestra que esa tubería es la entrada, y esa tubería no tiene una interfaz tty, es solo una secuencia de texto. Intentar crear un tty con eso fallará como indica el mensaje de error.

¿Puedo iniciar tty dentro de la ventana acoplable? Tengo alguna aplicación que deja de funcionar Si no ejecuto la ventana acoplable con -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ó con ‘- t’.

No es redundante, docker, puede crear un TTY sin asociar nada. Su salida tendría caracteres para el color, etc., pero la salida de su terminal no se canalizaría a la entrada del contenedor. Por lo tanto, los caracteres que escriba se pondrán en cola para el siguiente comando que ejecute después de que salga el comando de docker.