web-dev-qa-db-fra.com

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

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 le sais docker run's -t option signifie "Allocate a pseudo-TTY", et j'ai lu aperçus historiques de ce que TTY signifie , mais cela ne m'a pas aidé à comprendre quel type de contrat est violé ici.

19
Mikhail Vasin

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

  • par défaut (sans ni -i ni -t options) un conteneur Docker envoie uniquement sa sortie à STDOUT,
  • avec -i l'option vient de la connexion à STDIN,
  • -t L'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.
8
Mikhail Vasin

Réponse tardive, mais pourrait aider quelqu'un

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

Donc

  • docker run -i Alpine cat vous 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 cat attend l'entrée du flux infini qui est l'entrée terminale du docker run.
  • D'autre part echo "hello" | docker -i run Alpine cat affichera "bonjour" et quittera immédiatement car cat remarque que le flux d'entrée est terminé et se termine lui-même.

Si tu essayes docker ps une fois que vous avez quitté l'une des options ci-dessus, vous ne trouverez aucun conteneur en cours d'exécution. Dans les deux cas, cat lui-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 cat vous donnera une ligne vide, mais si vous essayez de taper "bonjour", vous n'obtiendrez aucun écho. En effet, alors que cat est connecté à une entrée de terminal, 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. cat attend 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 ps maintenant, vous voyez le conteneur cat toujours en cours d'exécution. Cela est dû au fait que cat attend toujours un flux d'entrée qui n'a jamais été fermé. Je n'ai trouvé aucune utilisation utile pour le -t seul sans être combiné avec -i.

Maintenant pour -it ensemble. Cela indique à cat que son entrée est une borne et en même temps connectez cette borne à l'entrée de docker run qui est un terminal. docker run/exec s'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 TTY si tu essayes echo "hello" | docker run -it Alpine cat car dans ce cas, l'entrée de docker run lui-même est le tube de l'écho précédent et non le terminal où docker run est exécuté

Enfin, pourquoi auriez-vous besoin de passer -t si -i fera l'astuce de connecter votre entrée à l'entrée de cat? 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 -p vous 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 sh vous donnera une ligne vide. Si vous tapez une commande comme ls, vous obtenez une sortie, mais vous n'obtiendrez pas de sortie d'invite ou colorée.

Dans les deux derniers cas, vous obtenez ce comportement car mysql ainsi que Shell ne traitaient pas l'entrée comme un tty et n'utilisaient donc pas de comportement spécifique tty comme masquer l'entrée ou colorer la sortie .

9
Ahmed Ghonim

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 en 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 montre votre exemple echo, 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.

4
BMitch