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

Este é um comando que funciona:

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

Este é um comando que responde com uma mensagem de erro:

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

Eu gostaria de descobrir exatamente o que acontece aqui. Não apenas "remover-t e será corrigido".

Eu sei que docker runde -t opção significa "alocar um pseudo-TTY", e eu li visões gerais históricas do que TTY representa, mas não me ajudou a entender que tipo de contrato é violado aqui.

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 si.

Entao

  • docker run -i alpine cat dá - lhe uma linha vazia à espera de entrada. Digite & quot; Olá & quot; você recebe um eco"Olá & quot;. O contêiner não sairá até que você envie CTRL + D porque o processo principal cat está aguardando a entrada do fluxo infinito que é a entrada do terminal do docker run.
  • Por outro lado echo "hello" | docker run -i alpine cat irá imprimir & quot; Olá & quot; e sair imediatamente porque cat percebe que o fluxo de Entrada terminou e termina a si mesmo.

Se você tentar docker ps depois de sair de qualquer um dos itens acima, você não encontrará nenhum contêiner em execução. Em ambos os casos, cat ele próprio terminou, portanto, o docker encerrou o contêiner.

Agora, para & quot;-t & quot;, isso informa ao processo principal dentro do docker que sua entrada é um dispositivo terminal.

Entao

  • docker run -t alpine cat vai lhe dar uma linha vazia, mas se você tentar digitar "Olá", Você não vai ter qualquer eco. Isso ocorre porque enquanto cat está conectado a uma entrada de terminal, Esta entrada não está conectada à sua entrada. O & quot; Olá & quot; que você digitou não atingiu a entrada de cat. cat está à espera de entrada que nunca chega.
  • echo "hello" | docker run -t alpine cat também lhe dará uma linha vazia e não sairá do contêiner em CTRL-D, mas você não receberá um eco & quot;Olá & quot; porque você não passou -i

Se você enviar CTRL + C, receberá seu shell de volta, mas se tentar docker ps agora, você vê o cat Recipiente ainda em execução. Isso é porque cat ainda está esperando em um fluxo de entrada que nunca foi fechado. Eu não encontrei nenhum uso útil para o -t sozinho sem ser combinado com -i.

Agora, para -it juntamente. Isso informa ao cat que sua entrada é um terminal e, ao mesmo tempo, conecta esse terminal à entrada de docker run que é um terminal. docker run/exec certifique-se de que sua própria entrada é de fato um tty antes de passá-lo para cat. É por isso que você terá um input device is not a TTY se você tentar echo "hello" | docker run -it alpine cat porque, neste caso, a entrada de docker run em si é o tubo do eco anterior e não o terminal onde docker run é executado

Finalmente, por que você precisaria passar -t se -i vai fazer o truque de conectar sua entrada para cata entrada? 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á um prompt de senha. Se você digitar a senha, os caracteres serão impressos visivelmente.
  • docker run -i alpine sh vai te dar uma linha vazia. Se você digitar um comando como ls você obtém uma saída, mas não obterá uma saída pronta ou colorida.

Nos dois últimos casos, você obtém esse comportamento porque mysql como shell não estavam tratando a entrada como um tty e, portanto, não usaram comportamento específico do tty, como mascarar a entrada ou colorir a saída.

Resposta ajudou-me a enrolar a cabeça:

  • por padrão (sem nenhum -i nem -t Opções) um contêiner Docker envia apenas seu toSTDOUT de saída,
  • com -i opção vem conexão com STDIN,
  • -t opção puxa em 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 o protocolo de interface do terminal. Tubulação de uma corda não.

Um tty indica que você tem um terminal, algo que seria fornecido pelo xterm ou uma das muitas interfaces de linha de comando do linux. Ele precisa de uma interface de saída de teclado e texto associada a ele. Razões típicas para querer isso é para suporte de saída de texto colorido, manipulação 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 o seu echo exemplo mostra, esse pipe é a entrada, e esse pipe não tem uma interface tty, é apenas um fluxo de texto. Tentar criar um tty com isso falhará como a mensagem de erro indica.

Posso iniciar o tty dentro do docker? Eu tenho algum aplicativo que para de funcionar, não executo o docker com ’ - T, mas não posso modificar o comando docker start na produção. Então eu preciso fazer o aplicativo pensar que foi iniciado com ' - t.

Não é redundante, o docker pode criar um TTY sem anexar nada a ele. Sua saída teria caracteres para cor, etc, mas a saída do terminal não seria canalizada para a entrada do contêiner. Portanto, os caracteres que você digita seriam enfileirados para o próximo comando executado após a saída do comando docker.