Confusa sobre a opção Docker -t para alocar um pseudo-TTY

207

O que exatamente essa opção faz? Eu tenho lido muito sobre TTY e ainda estou confuso. Eu brinquei com não ter o -te just -ie parece que programas que esperam que a entrada do usuário gerem um erro sem o -t. Por que é importante ativar o pseudo-TTY?

user1099123
fonte

Respostas:

223

A -topção vai para como o Unix / Linux lida com o acesso ao terminal. No passado, um terminal era uma conexão direta, mais tarde uma conexão baseada em modem. Eles tinham drivers de dispositivos físicos (eram peças de equipamento reais). Depois que as redes generalizadas entraram em uso, um driver pseudo-terminal foi desenvolvido. Isso ocorre porque ele cria uma separação entre a compreensão de quais recursos do terminal podem ser usados ​​sem a necessidade de gravá-lo diretamente no seu programa (leia as páginas de manual stty, curses).

Portanto, com isso como plano de fundo, execute um contêiner sem opções e, por padrão, você tem um fluxo stdout ( docker run | <cmd>funciona); executar com -i, e você adiciona o fluxo stdin (assim <cmd> | docker run -ifunciona); use -t, geralmente na combinação -ite você tenha um driver de terminal adicionado, que, se você estiver interagindo com o processo, provavelmente será o que deseja. Basicamente, faz o início do contêiner parecer uma sessão de conexão de terminal.

Twweeed
fonte
7
Essa deve ser a resposta principal. Embora não seja o mais técnico aqui, explica o comportamento fundamental das -itbandeiras.
Kris Khaira
1
Concordo com Kris. Eu li as outras respostas e ainda estava totalmente confuso. Esta resposta esclarece.
Ben Lee
4
Sim, talvez valha a pena mencionar que "TTY" em si é um acrônimo proveniente da palavra "teletypewriter" (AKA "teleprinter") que era um nome de dispositivo que permite digitar texto e enviá-lo ao mesmo tempo - como um telefone para texto ;-) Tente docker run -i ubuntue docker run -it ubuntuvocê verá a diferença imediatamente. "-i" permite que o contêiner aguarde a interação do host, mas a interação real do console (terminal) é possível após "alocar o driver tty" com o sinalizador "-t".
Zegar
Posso iniciar o tty na janela de encaixe? Tenho um aplicativo que para de funcionar e não executo a janela de encaixe -t, mas não consigo modificar o comando docker start em produção. Então, preciso fazer com que o aplicativo pense que foi iniciado -t.
mvorisek
97

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.

assim

  • docker run -i alpine catfornece uma linha vazia aguardando entrada. Digite "olá" para obter um eco "olá". O contêiner não sairá até que você envie CTRL+ Dporque o processo principal catestá aguardando a entrada do fluxo infinito que é a entrada do terminal docker run.
  • Por outro lado echo "hello" | docker run -i alpine cat, imprimirá "olá" e sairá imediatamente, porque catpercebe que o fluxo de entrada terminou e termina automaticamente .

Se você tentar docker psdepois de sair de qualquer um dos itens acima, não encontrará nenhum contêiner em execução. Nos dois casos, catele próprio foi finalizado, portanto, a janela de encaixe finalizou o contêiner.

Agora, para "-t", isso informa ao processo principal dentro da janela de encaixe que sua entrada é um dispositivo terminal.

assim

  • docker run -t alpine catfornecerá uma linha vazia, mas se você tentar digitar "olá", não receberá eco. Isso ocorre porque enquanto catestiver conectado a uma entrada do terminal, essa entrada não estará conectada à sua entrada. O "olá" que você digitou não atingiu a entrada de cat. catestá aguardando uma entrada que nunca chega.
  • echo "hello" | docker run -t alpine cattambém fornecerá uma linha vazia e não sairá do contêiner CTRL- Dmas você não receberá um "alô" de eco porque não passou-i

Se você enviar CTRL+ C, recuperará seu shell, mas se tentar docker psagora, verá o catcontêiner ainda em execução. Isso ocorre porque catainda está aguardando um fluxo de entrada que nunca foi fechado. Eu não encontrei nenhum uso útil para o -tsozinho, sem ser combinado com -i.

Agora, -itjuntos. Isso informa ao gato que sua entrada é um terminal e, ao mesmo tempo, conecta esse terminal à entrada da docker runqual é um terminal. docker run/execgarantirá que sua própria entrada seja de fato um tty antes de passá-la para cat. É por isso que você obterá um input device is not a TTYse tentar, echo "hello" | docker run -it alpine catporque nesse caso, a entrada em docker runsi é o canal do eco anterior e não o terminal onde docker runé executado

Finalmente, por que você precisaria aprovar -tse -ifará o truque de 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 -u root -pfornecerá uma solicitação de senha. Se você digitar a senha, os caracteres serão impressos visivelmente.
  • docker run -i alpine shlhe dará uma linha vazia. Se você digitar um comando como lsvocê obtém uma saída, mas não receberá uma saída rápida ou colorida.

Nos dois últimos casos, você tem esse comportamento porque mysql, assim como shellnão estavam tratando a entrada como um tty e, portanto, não utilizar tty comportamento específico como mascarar a entrada ou colorir a saída.

Ahmed Ghonim
fonte
6
A melhor resposta aqui que realmente me faz entender o que exatamente -te as -iopções fazem!
Ruslan Stelmachenko
1
Resposta fantástica, que antecipou todas as perguntas que eu tinha.
James Machin
@ Ahmed Ghonim, respostas muito boas. Obrigado. Mas sobre "Isso ocorre porque os comandos tratam a entrada de maneira diferente se for um terminal", acho que é um erro de digitação, certo? Deve ser "Isso ocorre porque os comandos tratam a entrada de maneira diferente se não for um terminal", certo?
tuq 4/01
@Ahmed Ghonim. Claro como cristal. Mas e quanto ao docker run -a = stdin alpine cat?
HKIT 29/01
1
@HKIIT "-a = stdin" anexa o fluxo stdin ao contêiner, mas sem uma alocação de memória. É o sinalizador -i que aloca memória buffer no contêiner para o fluxo stdin; portanto, a descrição "Mantenha o STDIN aberto, mesmo que não esteja anexado", quando -i é passado, a memória é alocada para o stdin, independentemente dos sinalizadores de anexo. Sem essa memória alocada, as leituras para stdin estão vazias / eof. Você também precisa incluir "-a = stdout" para ver a resposta do comando cat, por exemplo: "docker run -i -a = stdin -a = stdout alpine cat" ... é claro que não há necessidade de fazer isso, você pode basta executar "docker run -i alpine cat".
David D
71

O -targumento NÃO é bem documentado ou mencionado por muitas pessoas, de acordo com uma pesquisa no Google.

Ele nem aparece quando você exibe uma lista de (o que deveria ser) todos os argumentos do cliente docker digitando dockerno prompt do Bash (com a versão mais recente do 1.8.1).

De fato, se você tentar obter ajuda específica sobre esse argumento, digitar docker -t --helpif fornece uma resposta incrivelmente vaga:

sinalizador fornecido mas não definido: -t

Portanto, você não pode ser responsabilizado por estar confuso com esse argumento!

Há uma menção na documentação online do Docker que diz que é "Alocar um pseudo-tty" e é frequentemente usado com -i:

https://docs.docker.com/reference/run/

Vi-o usado na documentação para o fantástico jwilder/nginx-proxycontainer docker da seguinte maneira:

docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx

Nesse caso, o que ele faz é enviar a saída para o tty 'virtual' (prompt de comando do Bash / terminal) dentro desse contêiner do docker. Você pode ver essa saída executando o comando docker, docker logs CONTAINERonde CONTAINERestão os primeiros caracteres do ID desse contêiner. Esse ID do CONTAINER pode ser encontrado digitando-sedocker ps -a

Eu vi esse -targumento mencionado brevemente no link a seguir, onde diz

Os sinalizadores -te -ialocam uma pseudo-tty e mantêm o stdin aberto, mesmo que não estejam anexados. Isso permitirá que você use o contêiner como uma VM tradicional enquanto o prompt do bash estiver em execução.

https://coreos.com/os/docs/latest/getting-started-with-docker.html

Eu espero que isso ajude! Não sei por que isso não é documentado ou usado muito. Talvez seja experimental e seja implementado como um recurso documentado nas próximas versões.

Rico
fonte
21
A documentação aparece para docker run --help, não docker -t --help: -t, --tty=false Allocate a pseudo-TTY"
bskaggs
5

O que eu sei sobre o -té o seguinte:

docker exec -ti CONTAINER bash- permite-me "entrar" no contêiner. Parece ssh-ing (não é).

Mas o problema foi quando eu queria restaurar um banco de dados.

Normalmente eu faço docker exec -ti mysql.5.7 mysql- aqui eu executo o comando mysql no container e obtenho um terminal interativo.

Eu adicionei <dump.sqlao comando anterior para restaurar um banco de dados. Mas falhou cannot enable tty mode on non tty input.

Removendo o -tajudado. Ainda não entendo o porquê:

docker exec -i mysql.5.7 mysql < dump.sql

O último funciona. Espero que isso ajude as pessoas.

névoa
fonte
Posso iniciar o tty na janela de encaixe? Tenho um aplicativo que para de funcionar e não executo a janela de encaixe -t, mas não consigo modificar o comando docker start em produção. Então, preciso fazer com que o aplicativo pense que foi iniciado -t.
mvorisek
1

No Linux, quando você executa um comando, você precisa de um terminal (tty) para executá-lo.

Portanto, quando você deseja se conectar à janela de encaixe (ou executar o comando no contêiner de estação de encaixe), precisará fornecer a opção -t, que leva em consideração o terminal dentro do contêiner de estação de encaixe.

Chirag
fonte
0

Todo processo tem três fluxos de dados, ou seja STDIN/ STDOUT/ STDERR. Quando um processo está em execução em um contêiner, por padrão, o terminal é conectado ao fluxo STDOUT do processo em execução no contêiner. Portanto, todos os fluxos de saída serão visíveis durante a execução do docker runcomando no terminal. Mas se você deseja fornecer entrada para o processo em execução no contêiner, é necessário conectar-se ao canal STDIN do processo que não é por padrão e é feito com o docker run -icomando

-t é usado para operações de entrada interativas / formatadas.

Harsh Vardhan
fonte
-3

Ele -itinstrui o Docker a alocar um pseudo-TTY conectado ao stdin do contêiner, criando um shell bash interativo no contêiner.

--interactive, -i falseMantenha STDIN abrir mesmo que não seja anexado

--tty, -t false Aloque um pseudo-TTY

https://docs.docker.com/engine/reference/commandline/run/

Droid Teahouse
fonte