O que significa exatamente "o dispositivo de entrada não é um TTY" na saída "docker run"?

O que significa exatamente "o dispositivo de entrada não é um TTY" na saída "docker run"?

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 runa -topçã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 -iconectará o STDIN do comando dentro do contêiner ao STDIN do docker run/execpróprio.

Então

  • docker run -i alpine catfornece 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 principal catestá aguardando a entrada do fluxo infinito que é a entrada do terminal do arquivo docker run.
  • Por outro lado, echo "hello" | docker run -i alpine catirá imprimir "olá" e sair imediatamente porque catpercebe que o fluxo de entrada terminou e termina sozinho.

Se você tentar docker psdepois de sair de uma das opções acima, não encontrará nenhum contêiner em execução. Em ambos os casos, catele 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 catfornecerá uma linha vazia, mas se você tentar digitar "olá", não obterá nenhum eco. Isso ocorre porque enquanto catestá 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 de cat. catestá esperando por informações que nunca chegam.
  • echo "hello" | docker run -t alpine cattambé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 psagora, verá que o catcontêiner ainda está em execução. Isso ocorre porque catainda está aguardando um fluxo de entrada que nunca foi fechado. Não encontrei nenhum uso útil sozinho -tsem ser combinado com -i.

Agora, para -itjuntos. Isso diz ao cat que sua entrada é um terminal e ao mesmo tempo conecta este terminal à entrada docker runque é um terminal. docker run/execgarantirá 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 TTYif você tentar echo "hello" | docker run -it alpine catporque neste caso, a entrada em docker runsi é o pipe do eco anterior e não o terminal onde docker runé executado

Finalmente, por que você precisaria passar -tif -ipara conectar sua entrada à catentrada 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 -plhe dará uma solicitação de senha. Se você digitar a senha, os caracteres serão impressos de forma visível.
  • docker run -i alpine shlhe dará uma linha vazia. Se você digitar um comando como lsesse, 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 mysqltambém shellnã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 -inem -t) um contêiner Docker apenas envia sua saída para STDOUT,
  • com -iopção vem conexão com STDIN,
  • -topçã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 echomostra 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.

informação relacionada