compose - Confundido acerca de la opción Docker-t para asignar un pseudo-TTY
docker compose tty (6)
¿Qué hace exactamente esta opción?
He estado leyendo mucho en TTY y todavía estoy confundido.
Jugué con no tener el
-t
y solo
-i
y parece que los programas que esperan la entrada del usuario arrojan un error sin el
-t
.
¿Por qué es importante habilitar pseudo-TTY?
El
-it
indica a Docker que asigne un pseudo-TTY conectado al stdin del contenedor, creando un shell bash interactivo en el contenedor.
--interactive
,
-i
false
Mantenga STDIN abierto incluso si no está conectado
--tty
,
-t
false
--tty
un pseudo-TTY
El argumento
-t
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 de
docker
escribiendo
docker
en 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 --help
if 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 contenedor acoplable
jwilder/nginx-proxy
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 logs CONTAINER
donde
CONTAINER
es el primer par de caracteres de la ID de este contenedor.
Este ID DE CONTENEDOR se puede encontrar escribiendo
docker ps -a
He visto este argumento
-t
mencionado brevemente en el siguiente enlace, donde dice
Los indicadores
-t
y-i
asignan 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.
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 tiene en cuenta la terminal dentro del contenedor de la ventana acoplable.
La opción
-t
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 se debe a que crea una separación entre comprender qué capacidades de terminal se pueden usar sin la necesidad de escribirlo directamente en su programa (lea las páginas de
stty
en
stty
,
curses
).
Entonces, con eso como fondo, ejecute un contenedor sin opciones y, de forma predeterminada, tiene una secuencia stdout (por lo que
docker run | <cmd>
funciona);
ejecute con
-i
, y obtendrá la secuencia stdin agregada (entonces
<cmd> | docker run -i
funciona);
use
-t
, generalmente en la combinación
-it
y tiene un controlador de terminal agregado, que si está interactuando con el proceso, probablemente sea lo que desea.
Básicamente, hace que el inicio del contenedor parezca una sesión de conexión de terminal.
Lo que sé sobre
-t
es 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 fue cuando quise restaurar una base de datos.
Usualmente hago
docker exec -ti mysql.5.7 mysql
- Aquí ejecuto el comando mysql en el contenedor y obtengo un terminal interactivo.
<dump.sql
al comando anterior para poder restaurar un db.
Pero falló con
cannot enable tty mode on non tty input
.
Eliminar el
-t
ayudó.
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.
Respuesta tardía, pero podría ayudar a alguien
docker run/exec -i
conectará el STDIN del comando dentro del contenedor al STDIN del mismo
docker run/exec
.
Entonces
-
docker run -i alpine cat
le 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 + D porque el proceso principalcat
está esperando la entrada del flujo infinito que es la entrada del terminal de ladocker run
. -
Por otro lado
echo "hello" | docker -i run alpine cat
echo "hello" | docker -i run alpine cat
imprimirá "hola" y saldrá inmediatamente porquecat
da cuenta de que la secuencia de entrada ha finalizado y termina por sí misma.
Si prueba
docker ps
después de salir de cualquiera de los anteriores, no encontrará ningún contenedor en ejecución.
En ambos casos, el
cat
mismo 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 cat
le dará una línea vacía, pero si intenta escribir "hola", no obtendrá ningún eco. Esto se debe a que mientrascat
está conectado a una entrada de terminal, esta entrada no está conectada a su entrada. El "hola" que escribió no alcanzó la entrada decat
.cat
está esperando una entrada que nunca llega. -
echo "hello" | docker run -t alpine cat
echo "hello" | docker run -t alpine cat
también le dará una línea vacía y no saldrá del contenedor en CTRL - D pero no obtendrá un eco "hola" porque no pasó-i
Si envía
CTRL
+
C
, recupera su shell, pero si prueba
docker ps
ahora, verá que el contenedor
cat
todavía se está ejecutando.
Esto se debe a que
cat
todavía está esperando una secuencia de entrada que nunca se cerró.
No he encontrado ningún uso útil para
-t
solo sin combinarlo con
-i
.
Ahora, para
-it
juntos.
Esto le dice a cat que su entrada es una terminal y al mismo tiempo conecte esta 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 intenta
echo "hello" | docker run -it alpine cat
echo "hello" | docker run -it alpine cat
porque en este caso, la entrada de
docker run
es la tubería del eco anterior y no el terminal donde se
docker run
Finalmente, ¿por qué necesitaría pasar
-t
si
-i
hará el truco de conectar su entrada a la entrada de
cat
?
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 -uroot -p
le dará una solicitud de contraseña. Si escribe la contraseña, los caracteres se imprimen visiblemente. -
docker run -i alpine sh
te dará una línea vacía. Si escribe un comando comols
obtendrá un resultado, pero no obtendrá un mensaje o un resultado en color.
En los últimos dos casos, obtienes este comportamiento porque
mysql
y
shell
no trataban la entrada como tty y, por lo tanto, no usaban un comportamiento específico de tty como enmascarar la entrada o colorear la salida.