Confuso sull'opzione Docker -t per allocare uno pseudo-TTY


208

Cosa fa esattamente questa opzione? Ho letto molto su TTY e sono ancora confuso. Ho giocato senza avere il -te giusto -ie sembra che i programmi che prevedono l'input dell'utente generano un errore senza il -t. Perché è importante abilitare lo pseudo-TTY?

Risposte:


224

L' -topzione va a come Unix / Linux gestisce l'accesso al terminale. In passato, un terminale era una connessione fissa, in seguito una connessione basata su modem. Questi avevano driver di dispositivi fisici (erano veri e propri equipaggiamenti). Una volta che sono state utilizzate le reti generalizzate, è stato sviluppato un driver pseudo-terminale. Questo perché crea una separazione tra la comprensione di quali funzionalità terminali possono essere utilizzate senza la necessità di scriverle direttamente nel programma (leggere le pagine man su stty, curses).

Quindi, con quello come sfondo, esegui un contenitore senza opzioni e per impostazione predefinita hai un flusso stdout (quindi docker run | <cmd>funziona); corri con -ie ottieni lo stream stdin aggiunto (quindi <cmd> | docker run -ifunziona); usa -t, di solito nella combinazione -ite hai aggiunto un driver terminale, che se stai interagendo con il processo è probabilmente quello che vuoi. Fondamentalmente fa apparire il container come una sessione di connessione terminale.


7
Questa dovrebbe essere la risposta migliore. Sebbene non sia il più tecnico qui, spiega il comportamento fondamentale delle -itbandiere.
Kris Khaira,

1
D'accordo con Kris. Ho letto le altre risposte ed ero ancora totalmente confuso. Questa risposta lo chiarisce.
Ben Lee,

4
Sì, forse vale la pena ricordare che "TTY" stesso è un acronimo che deriva dalla parola "teletypewriter" (AKA "teleprinter") che era un nome di dispositivo che consente di digitare il testo e inviarlo via nello stesso momento - come un telefono per il testo ;-) Prova docker run -i ubuntue docker run -it ubuntuvedrai immediatamente la differenza. "-i" consente di attendere che il contenitore attenda l'interazione dall'host ma l'interazione effettiva dalla console (terminale) è possibile dopo aver "allocato tty driver" con flag "-t".
Zegar,

Posso avviare tty nella finestra mobile? Ho alcune app che smettono di funzionare se non eseguo la finestra mobile -t, ma non riesco a modificare il comando di avvio della finestra mobile in produzione. Quindi devo fare in modo che l'app pensi che sia stata avviata -t.
mvorisek,

98

Risposta in ritardo, ma potrebbe aiutare qualcuno

docker run/exec -icollegherà lo STDIN del comando all'interno del contenitore allo STDIN dello docker run/execstesso.

Così

  • docker run -i alpine catti dà una riga vuota in attesa di input. Digita "ciao" ottieni l'eco "ciao". Il contenitore non uscirà finché non si invia CTRL+ Dperché il processo principale catè in attesa di input dal flusso infinito che è l'input del terminale di docker run.
  • D'altra parte echo "hello" | docker run -i alpine catstamperà "ciao" e uscirà immediatamente perché catnota che il flusso di input è terminato e termina da solo.

Se si tenta docker psdi uscire da uno dei precedenti, non si troveranno contenitori in esecuzione. In entrambi i casi, catè terminato, quindi la finestra mobile ha terminato il contenitore.

Ora per "-t", questo dice al processo principale all'interno della finestra mobile che il suo input è un dispositivo terminale.

Così

  • docker run -t alpine catti darà una riga vuota, ma se provi a digitare "ciao", non otterrai alcun eco. Questo perché mentre catè collegato a un ingresso terminale, questo ingresso non è collegato al tuo ingresso. Il "ciao" che hai digitato non ha raggiunto l'input di cat. catè in attesa di input che non arrivano mai.
  • echo "hello" | docker run -t alpine catti darà anche una riga vuota e non uscirà dal contenitore CTRL- Dma non otterrai un eco "ciao" perché non hai superato-i

Se si invia CTRL+ C, si ottiene indietro la shell, ma se si tenta docker psora, si vede il catcontenitore ancora in esecuzione. Questo perché catè ancora in attesa su un flusso di input che non è mai stato chiuso. Non ho trovato alcun uso utile per il -tsolo senza essere combinato con -i.

Ora, per -itinsieme. Questo dice a cat che il suo input è un terminale e allo stesso tempo collega questo terminale al cui input docker runè un terminale. docker run/execfarà in modo che il proprio input sia in realtà un tty prima di passarlo a cat. Questo è il motivo per cui otterrai un input device is not a TTYse provi echo "hello" | docker run -it alpine catperché in questo caso, l'input di docker runse stesso è la pipe dell'eco precedente e non il terminale in cui docker runviene eseguito

Infine, perché dovresti passare -tse -ifarà il trucco di collegare l'input catall'input? Questo perché i comandi trattano l'input in modo diverso se si tratta di un terminale. Anche questo è meglio illustrato dall'esempio

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -u root -pti darà una richiesta di password. Se si digita la password, i caratteri vengono stampati visibilmente.
  • docker run -i alpine shti darà una riga vuota. Se si digita un comando come se lssi ottenga un output, ma non si riceverà un prompt o un output colorato.

Negli ultimi due casi, si ottiene questo comportamento perché mysqloltre a shellnon trattare l'input come tty e quindi non ha utilizzato un comportamento specifico di tty come mascherare l'input o colorare l'output.


6
La migliore risposta qui che mi fa davvero capire cosa fanno esattamente -te le -iopzioni!
Ruslan Stelmachenko,

1
Risposta fantastica che anticipava ogni mia domanda
James Machin il

@Ahmed Ghonim, ottime risposte. Grazie. Ma riguardo a "Questo perché i comandi trattano l'input in modo diverso se si tratta di un terminale", penso che sia un errore di digitazione, giusto? Dovrebbe essere "Questo perché i comandi trattano l'input in modo diverso se non è un terminale", giusto?
martedì

@Ahmed Ghonim. Cristallino. Ma che dire della docker run -a = stdin alpine cat?
HKIT

1
@HKIIT "-a = stdin" collega il flusso stdin al contenitore ma senza allocazione di memoria. È il flag -i che alloca memoria buffer nel contenitore per il flusso stdin, quindi la descrizione "Mantieni STDIN aperto anche se non collegato", quando viene passato -i la memoria viene allocata per stdin indipendentemente dai flag allegato. Senza questa memoria allocata le letture su stdin sono vuote / eof. Inoltre devi includere "-a = stdout" per vedere la risposta dal comando cat, ad esempio: "docker run -i -a = stdin -a = stdout alpine cat" ... ovviamente non è necessario farlo, puoi basta eseguire "docker run -i alpine cat".
David D

71

L' -targomento NON è ben documentato o menzionato spesso da molte persone, secondo una ricerca di Google.

Non compare nemmeno quando si visualizza un elenco di (cosa dovrebbe essere) tutti gli argomenti del client docker digitando dockeral prompt di Bash (con l'ultima versione di 1.8.1).

In effetti, se cerchi di ottenere un aiuto specifico su questo argomento digitando docker -t --helpif dà questa risposta incredibilmente vaga:

flag fornito ma non definito: -t

Quindi, non puoi essere incolpato per essere confuso su questo argomento!

C'è una menzione nella documentazione online di Docker che dice che è "Allocare uno pseudo-tty" ed è spesso usato con -i:

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

L'ho visto usato nella documentazione per il fantastico jwilder/nginx-proxycontenitore docker nel modo seguente:

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

In questo caso, ciò che fa è inviare l'output al tty 'virtuale' (prompt / terminale di comando Bash) all'interno di questo contenitore finestra mobile. È quindi possibile visualizzare questo output eseguendo il comando docker docker logs CONTAINERdove CONTAINERsono i primi due caratteri dell'ID di questo contenitore. Questo ID CONTENITORE può essere trovato digitandodocker ps -a

Ho visto questa -tdiscussione menzionata brevemente nel seguente link, dove dice

I flag -te -iassegnano una pseudo-tty e mantengono aperto lo stdin anche se non collegato. Ciò ti consentirà di utilizzare il contenitore come una macchina virtuale tradizionale finché il prompt di bash è in esecuzione.

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

Spero che aiuti! Non sono sicuro del perché questo non sia documentato o utilizzato molto. Forse è sperimentale e verrà implementato come funzionalità documentata nelle prossime versioni.


21
La documentazione si presenta docker run --helpnon per docker -t --help: -t, --tty=false Allocate a pseudo-TTY"
bskaggs

5

Quello che so di questo -tè il seguente:

docker exec -ti CONTAINER bash- mi permette di "accedere" nel contenitore. Sembra ssh-ing (non lo è).

Ma il problema era quando volevo ripristinare un database.

Di solito lo faccio docker exec -ti mysql.5.7 mysql- Qui eseguo il comando mysql nel contenitore e ottengo un terminale interattivo.

Ho aggiunto <dump.sqlal comando precedente in modo da poter ripristinare un db. Ma fallì cannot enable tty mode on non tty input.

Rimozione -tdell'aiuto. Ancora non capisco perché:

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

L'ultimo funziona. Spero che questo aiuti le persone.


Posso avviare tty nella finestra mobile? Ho alcune app che smettono di funzionare se non eseguo la finestra mobile -t, ma non riesco a modificare il comando di avvio della finestra mobile in produzione. Quindi devo fare in modo che l'app pensi che sia stata avviata -t.
mvorisek,

1

In Linux quando si esegue un comando, è necessario un terminale (tty) per eseguirlo.

Pertanto, quando si desidera connettersi alla finestra mobile (o eseguire il comando nel contenitore finestra mobile), è necessario fornire l'opzione -t che prende in considerazione il terminale all'interno del contenitore finestra mobile.


0

Ogni processo ha tre flussi di dati, ad es STDIN/ STDOUT/ STDERR. Quando un processo è in esecuzione in un contenitore, per impostazione predefinita il terminale è collegato al flusso STDOUT del processo in esecuzione nel contenitore. Quindi tutti i flussi di output saranno visibili durante l'esecuzione del docker runcomando nel terminale. Ma se si desidera fornire input al processo in esecuzione nel contenitore, è necessario connettersi con il canale STDIN del processo che non è predefinito e viene eseguito condocker run -i comando.

-t viene utilizzato per operazioni di input interattive / formattate.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.