Este é um comando que funciona:
$ echo 'hi there' | docker run -i ubuntu cat
hi there
Este é um comando que responde com uma mensagem de erro:
$ echo 'hi there' | docker run -it ubuntu cat
the input device is not a TTY
Eu gostaria de descobrir exatamente o que acontece aqui. Não apenas "remova -t e será consertado".
Eu sei que docker run
a -t
opção significa "Alocar um pseudo-TTY" e livisões gerais históricas do que TTY significa, mas não me ajudou a entender que tipo de contrato é violado aqui.
Responder1
Resposta tardia, mas pode ajudar alguém
docker run/exec -i
conectará o STDIN do comando dentro do contêiner ao STDIN do docker run/exec
próprio.
Então
docker run -i alpine cat
fornece uma linha vazia aguardando entrada. Digite "olá" e você receberá um eco "olá". O contêiner não será encerrado até que você envie CTRL+D porque o processo principalcat
está aguardando a entrada do fluxo infinito que é a entrada do terminal do arquivodocker run
.- Por outro lado,
echo "hello" | docker run -i alpine cat
irá imprimir "olá" e sair imediatamente porquecat
percebe que o fluxo de entrada terminou e termina sozinho.
Se você tentar docker ps
depois de sair de uma das opções acima, não encontrará nenhum contêiner em execução. Em ambos os casos, cat
ele próprio foi encerrado, portanto o docker encerrou o contêiner.
Agora, para "-t", informa ao processo principal dentro do docker que sua entrada é um dispositivo terminal.
Então
docker run -t alpine cat
fornecerá uma linha vazia, mas se você tentar digitar "olá", não obterá nenhum eco. Isso ocorre porque enquantocat
está conectado a uma entrada de terminal, esta entrada não está conectada à sua entrada. O "olá" que você digitou não alcançou a entrada decat
.cat
está esperando por informações que nunca chegam.echo "hello" | docker run -t alpine cat
também fornecerá uma linha vazia e não sairá do contêiner em CTRL-D, mas você não receberá um eco "olá" porque não passou-i
Se você enviar CTRL+C, você receberá seu shell de volta, mas se tentar docker ps
agora, verá que o cat
contêiner ainda está em execução. Isso ocorre porque cat
ainda está aguardando um fluxo de entrada que nunca foi fechado. Não encontrei nenhum uso útil sozinho -t
sem ser combinado com -i
.
Agora, para -it
juntos. Isso diz ao cat que sua entrada é um terminal e ao mesmo tempo conecta este terminal à entrada docker run
que é um terminal. docker run/exec
garantirá que sua própria entrada seja de fato tty antes de passá-la para cat
. É por isso que você receberá um input device is not a TTY
if você tentar echo "hello" | docker run -it alpine cat
porque neste caso, a entrada em docker run
si é o pipe do eco anterior e não o terminal onde docker run
é executado
Finalmente, por que você precisaria passar -t
if -i
para conectar sua entrada à cat
entrada de ? Isso ocorre porque os comandos tratam a entrada de maneira diferente se for um terminal. Isso também é melhor ilustrado pelo exemplo
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p
lhe dará uma solicitação de senha. Se você digitar a senha, os caracteres serão impressos de forma visível.docker run -i alpine sh
lhe dará uma linha vazia. Se você digitar um comando comols
esse, obterá uma saída, mas não obterá um prompt ou uma saída colorida.
Nos dois últimos casos, você obtém esse comportamento porque mysql
também shell
não estava tratando a entrada como um tty e, portanto, não usou um comportamento específico do tty, como mascarar a entrada ou colorir a saída.
Responder2
Esta respostame ajudou a entender:
- por padrão (sem opções
-i
nem-t
) um contêiner Docker apenas envia sua saída para STDOUT, - com
-i
opção vem conexão com STDIN, -t
opção puxa um driver de interface de terminal, que funciona em cima de STDIN/STDOUT. E quando um driver de terminal é puxado, a comunicação com um contêiner deve estar em conformidade com oprotocolo de interface de terminal. Canalizar uma string não.
Responder3
Um tty indica que você tem um terminal, algo que seria fornecido pelo xterm ou por uma das muitas interfaces de linha de comando do Linux. Ele precisa de um teclado e uma interface de saída de texto associada a ele. Os motivos típicos para querer isso são o suporte à saída de texto colorido, o manuseio de várias combinações de teclas (como as teclas de seta) e a capacidade de mover o cursor pela tela.
Quando você canaliza um comando para o docker, como echo
mostra seu exemplo, esse canal é a entrada e esse canal não possui uma interface tty, é apenas um fluxo de texto. A tentativa de criar um tty com isso falhará, conforme indica a mensagem de erro.