Confus au sujet de l'option Docker -t pour allouer un pseudo-ATS


208

Que fait exactement cette option? J'ai beaucoup lu sur TTY et je suis toujours confus. J'ai joué avec le fait de ne pas avoir le -tet juste -iet il semble que les programmes qui s'attendent à ce que la saisie de l'utilisateur génère une erreur sans le -t. Pourquoi est-il important d'activer le pseudo-ATS?

Réponses:


224

L' -toption va à la façon dont Unix / Linux gère l'accès au terminal. Dans le passé, un terminal était une connexion matérielle, plus tard une connexion basée sur un modem. Ceux-ci avaient des pilotes de périphériques physiques (c'étaient de vrais équipements). Une fois les réseaux généralisés mis en service, un pilote pseudo-terminal a été développé. En effet, cela crée une séparation entre la compréhension des capacités des terminaux qui peuvent être utilisées sans avoir besoin de les écrire directement dans votre programme (lire les pages de manuel stty, curses).

Donc, avec cela en arrière-plan, exécutez un conteneur sans options et par défaut, vous avez un flux stdout (donc ça docker run | <cmd>marche); exécutez avec -i, et vous obtenez un flux stdin ajouté (donc ça <cmd> | docker run -imarche); utilisez -t, généralement dans la combinaison -itet vous avez un pilote de terminal ajouté, qui si vous interagissez avec le processus est probablement ce que vous voulez. Cela fait que le démarrage du conteneur ressemble à une session de connexion de terminal.


7
Cela devrait être la meilleure réponse. Bien que ce ne soit pas le plus technique ici, il explique le comportement fondamental des -itdrapeaux.
Kris Khaira

1
D'accord avec Kris. J'ai lu les autres réponses et j'étais toujours totalement confus. Cette réponse l'éclaircit.
Ben Lee

4
Oui, il vaut peut-être la peine de mentionner que "TTY" lui-même est un acronyme provenant du mot "teletypewriter" (AKA "teleprinter") qui était un nom d'appareil vous permettant de taper du texte et de l'envoyer en même temps - comme un téléphone pour le texte ;-) Essayez docker run -i ubuntuet docker run -it ubuntuvous verrez immédiatement la différence. "-i" vous permet de faire en sorte que le conteneur attende l'interaction de l'hôte, mais une interaction réelle depuis la console (terminal) est possible après avoir "alloué le pilote tty" avec l'indicateur "-t".
Zegar

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

98

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.

Alors

  • docker run -i alpine catvous donne une ligne vide en attente de saisie. Tapez "bonjour" vous obtenez un écho "bonjour". Le conteneur ne sortira pas tant que vous n'aurez pas envoyé CTRL+ Dcar 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 run -i alpine cataffichera "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'un des éléments 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.

Alors

  • 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 catvous donnera également une ligne vide et ne quittera pas le conteneur CTRL- Dmais vous n'aurez 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 une borne et en même temps connectez cette borne à l'entrée docker rundont est une borne. 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 -u root -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 si lsvous obteniez 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.


6
La meilleure réponse ici qui me fait vraiment comprendre ce exactement -tet les -ioptions font!
Ruslan Stelmachenko

1
Une réponse fantastique qui a anticipé toutes mes questions
James Machin

@Ahmed Ghonim, Très bonnes réponses. Je vous remercie. Mais à propos de "C'est parce que les commandes traitent l'entrée différemment s'il s'agit d'un terminal", je pense que c'est une faute de frappe, non? Cela devrait être "C'est parce que les commandes traitent l'entrée différemment si ce n'est pas un terminal", non?
tuq

@Ahmed Ghonim. Clair comme de l'eau de roche. Mais qu'en est-il du docker run -a = stdin alpine cat?
HKIT

1
@HKIIT "-a = stdin" attache le flux stdin au conteneur mais sans allocation de mémoire. C'est l'indicateur -i qui alloue de la mémoire tampon dans le conteneur pour le flux stdin, d'où la description "Garder STDIN ouvert même s'il n'est pas attaché", lorsque -i est transmis, la mémoire est allouée à stdin indépendamment des indicateurs d'attachement. Sans cette mémoire allouée, les lectures vers stdin sont vides / eof. Vous devez également inclure "-a = stdout" pour voir la réponse de la commande cat par exemple: "docker run -i -a = stdin -a = stdout alpine cat" ... bien sûr, il n'est pas nécessaire de le faire, vous pouvez lancez simplement "docker run -i alpine cat".
David D

71

L' -targument n'est PAS bien documenté, ou souvent mentionné par de nombreuses personnes, selon une recherche Google.

Il n'apparaît même pas lorsque vous affichez une liste de (ce qui devrait être) tous les arguments du client docker en tapant dockerà l'invite Bash (avec la dernière version de 1.8.1).

En fait, si vous essayez d'obtenir une aide spécifique sur cet argument en tapant docker -t --helpif donne cette réponse incroyablement vague:

indicateur fourni mais non défini: -t

Vous ne pouvez donc pas être blâmé d'être confus à propos de cet argument!

Il y a une mention dans la documentation en ligne Docker qui dit que c'est "Allouer un pseudo-tty" et qui est souvent utilisée avec -i:

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

Je l'ai vu utilisé dans la documentation du formidable jwilder/nginx-proxyconteneur Docker de la manière suivante:

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

Dans ce cas, il envoie la sortie au terminal «virtuel» (invite de commande Bash / terminal) dans ce conteneur Docker. Vous pouvez ensuite voir cette sortie en exécutant la commande docker docker logs CONTAINERoù se CONTAINERtrouve le premier couple de caractères de l'ID de ce conteneur. Cet ID DE CONTENEUR peut être trouvé en tapantdocker ps -a

J'ai vu cet -targument mentionné brièvement dans le lien suivant, où il est dit

Les drapeaux -tet -iallouent un pseudo-tty et maintiennent stdin ouvert même s'il n'est pas attaché. Cela vous permettra d'utiliser le conteneur comme une machine virtuelle traditionnelle tant que l'invite bash est en cours d'exécution.

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

J'espère que ça aide! Je ne sais pas pourquoi cela n'est pas documenté ou utilisé beaucoup. Peut-être que c'est expérimental et sera implémenté en tant que fonctionnalité documentée dans les prochaines versions.


21
La documentation s'affiche pour docker run --help, pas docker -t --help: -t, --tty=false Allocate a pseudo-TTY"
bskaggs

5

Ce que je sais de -tce qui suit est le suivant:

docker exec -ti CONTAINER bash- me permet de "me connecter" dans le conteneur. On dirait du sh-ing (ce n'est pas le cas).

Mais le problème était quand je voulais restaurer une base de données.

Habituellement, je le fais docker exec -ti mysql.5.7 mysql- Ici, j'exécute la commande mysql dans le conteneur et obtient un terminal interactif.

J'ai ajouté <dump.sqlà la commande précédente pour pouvoir restaurer une base de données. Mais cela a échoué cannot enable tty mode on non tty input.

Suppression de l' -taide. Je ne comprends toujours pas pourquoi:

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

Le dernier fonctionne. J'espère que cela aide les gens.


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

1

Sous Linux, lorsque vous exécutez une commande, vous avez besoin d'un terminal (tty) pour l'exécuter.

Ainsi, lorsque vous souhaitez vous connecter à Docker (ou exécuter la commande dans le conteneur Docker), vous devez fournir l'option -t qui prend en compte le terminal à l'intérieur du conteneur Docker.


0

Chaque processus a trois flux de données, à savoir STDIN/ STDOUT/ STDERR. Lorsqu'un processus s'exécute dans un conteneur, le terminal par défaut est connecté au flux STDOUT du processus s'exécutant dans le conteneur. Par conséquent, tous les flux de sortie seront visibles lors de l'exécution de la docker runcommande dans le terminal. Mais si vous souhaitez fournir une entrée au processus en cours d'exécution dans le conteneur, vous devez vous connecter avec le canal STDIN du processus qui n'est pas par défaut et se fait avec la docker run -icommande.

-t est utilisé pour les opérations d'entrée interactives / formatées.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.