Que signifie exactement «le périphérique d'entrée n'est pas un ATS» dans la sortie «docker run»?

18

Ceci est une commande qui fonctionne:

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

Il s'agit d'une commande qui répond avec un message d'erreur:

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

Je voudrais savoir exactement ce qui se passe ici. Pas seulement "supprimer -t et ce sera corrigé".

Je sais que docker runde » -toption signifie « Allouer un pseudo-ATS », et j'ai lu un aperçu historique de ce ATS signifie , mais il ne me aider à comprendre quel genre de contrat est violée ici.

Mikhail Vasin
la source
Ce n'est pas redondant, Docker peut créer un ATS sans y attacher quoi que ce soit. Votre sortie aurait des caractères pour la couleur, etc., mais la sortie de votre terminal ne serait pas dirigée vers l'entrée du conteneur. Ainsi, les caractères que vous tapez seront mis en file d'attente pour la prochaine commande que vous exécutez après la sortie de la commande docker.
BMitch
Puis-je démarrer tty dans le docker? J'ai une application qui cesse de fonctionner avec laquelle je n'exécute pas le docker -t, mais je ne peux pas modifier la commande docker start en production. Je dois donc faire croire à l'application qu'elle a commencé -t.
mvorisek

Réponses:

9

Cette réponse m'a aidé à envelopper ma tête:

  • par défaut (sans ni -ini -toptions) un conteneur Docker envoie uniquement sa sortie à STDOUT,
  • avec -ioption vient la connexion à STDIN,
  • -tL'option extrait un pilote d'interface de terminal , qui fonctionne au-dessus de STDIN / STDOUT. Et lorsqu'un pilote de terminal est intercepté, la communication avec un conteneur doit être conforme au protocole d'interface du terminal . Le piping d'une chaîne ne fonctionne pas.
Mikhail Vasin
la source
7

Réponse tardive, mais pourrait aider quelqu'un

docker run/exec -iconnectera le STDIN de la commande à l'intérieur du conteneur au STDIN de docker run/execlui - même.

Donc

  • docker run -i alpine catvous donne une ligne vide en attente de saisie. Tapez "bonjour" vous obtenez un écho "bonjour". Le conteneur ne se fermera pas tant que vous n'aurez pas envoyé CTRL + D car le processus principal catattend l'entrée du flux infini qui est l'entrée terminale du docker run.
  • D'un autre côté echo "hello" | docker -i run alpine cat, imprimera "bonjour" et quittera immédiatement car il catremarque que le flux d'entrée s'est terminé et se termine lui-même.

Si vous essayez docker psaprès avoir quitté l'une des options ci-dessus, vous ne trouverez aucun conteneur en cours d'exécution. Dans les deux cas, catlui - même s'est terminé, donc docker a terminé le conteneur.

Maintenant pour "-t", cela indique au processus principal dans docker que son entrée est un terminal.

Donc

  • docker run -t alpine catvous donnera une ligne vide, mais si vous essayez de taper "bonjour", vous n'obtiendrez aucun écho. En effet, alors que catest connecté à une entrée de borne, cette entrée n'est pas connectée à votre entrée. Le "bonjour" que vous avez tapé n'a pas atteint l'entrée de cat. catattend une entrée qui n'arrive jamais.
  • echo "hello" | docker run -t alpine cat vous donnera également une ligne vide et ne quittera pas le conteneur sur CTRL-D mais vous n'obtiendrez pas d'écho "bonjour" car vous n'avez pas réussi -i

Si vous envoyez CTRL + C, vous récupérez votre shell, mais si vous essayez docker psmaintenant, vous voyez le catconteneur toujours en cours d'exécution. En effet, catil attend toujours un flux d'entrée qui n'a jamais été fermé. Je n'ai trouvé aucune utilisation utile pour le -tseul sans être combiné avec -i.

Maintenant, pour -itensemble. Cela indique à cat que son entrée est un terminal et en même temps connectez ce terminal à l'entrée docker rundont est un terminal. docker run/execs'assurera que sa propre entrée est en fait un tty avant de la passer à cat. C'est pourquoi vous obtiendrez un input device is not a TTYsi vous essayez echo "hello" | docker run -it alpine catcar dans ce cas, l'entrée en docker runelle-même est le canal de l'écho précédent et non le terminal où docker runest exécuté

Enfin, pourquoi auriez-vous besoin de réussir -tsi vous réussissez à -iconnecter votre entrée à celle catde? En effet, les commandes traitent l'entrée différemment s'il s'agit d'un terminal. Ceci est également mieux illustré par l'exemple

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -pvous donnera une invite de mot de passe. Si vous saisissez le mot de passe, les caractères sont imprimés visiblement.
  • docker run -i alpine shvous donnera une ligne vide. Si vous tapez une commande comme lsvous obtenez une sortie, mais vous n'obtiendrez pas une invite ou une sortie colorée.

Dans les deux derniers cas, vous obtenez ce comportement parce mysqlque vous shellne traitez pas l'entrée comme un tty et n'utilisez donc pas de comportement spécifique au tty comme masquer l'entrée ou colorer la sortie.

Ahmed Ghonim
la source
4

Un tty indique que vous avez un terminal, quelque chose qui serait fourni par xterm ou l'une des nombreuses interfaces de ligne de commande Linux. Il a besoin d'un clavier et d'une interface de sortie de texte qui lui sont associés. Les raisons typiques de vouloir cela sont la prise en charge de la sortie de texte couleur, la gestion de diverses combinaisons de touches (comme les touches fléchées) et la possibilité de déplacer le curseur sur l'écran.

Lorsque vous dirigez une commande dans Docker comme le echomontre votre exemple, ce canal est l'entrée et ce canal n'a pas d'interface tty, c'est juste un flux de texte. Tenter de créer un tty avec qui échouera comme l'indique le message d'erreur.

BMitch
la source
Il y a encore un écart pour moi entre "un clavier et une interface de sortie" et "STDIN / STDOUT". De toute évidence, vous ne pouvez pas appliquer le concept de "position du curseur" à STDOUT, car STDOUT est un flux, pas un écran. Quelles spécifications décrivent l'abstraction de l'interface de sortie qui est (je suppose) au-dessus de STDOUT?
Mikhail Vasin
1
C'est une interface qui s'exécute au-dessus de stdin / stdout. en.wikipedia.org/wiki/POSIX_terminal_interface
BMitch