Bingung tentang opsi Docker -t untuk Mengalokasikan pseudo-TTY


208

Apa sebenarnya yang dilakukan opsi ini? Saya sudah banyak membaca tentang TTY dan saya masih bingung. Saya bermain - main dengan tidak memiliki -tdan hanya -idan sepertinya program yang mengharapkan input pengguna membuat kesalahan tanpa -t. Mengapa pseudo-TTY penting untuk diaktifkan?

Jawaban:


224

The -tpilihan pergi ke bagaimana Unix / Linux menangani akses terminal. Di masa lalu, terminal adalah koneksi garis keras, kemudian koneksi berbasis modem. Ini memiliki driver perangkat fisik (mereka adalah peralatan nyata). Setelah jaringan umum mulai digunakan, driver pseudo-terminal dikembangkan. Ini karena ini menciptakan pemisahan antara memahami kemampuan terminal apa yang dapat digunakan tanpa perlu menuliskannya langsung ke program Anda (baca halaman manual stty, curses).

Jadi, dengan itu sebagai latar belakang, jalankan wadah tanpa opsi dan secara default Anda memiliki aliran stdout ( docker run | <cmd>berfungsi); dijalankan dengan -i, dan Anda mendapatkan aliran stdin ditambahkan ( <cmd> | docker run -iberfungsi); gunakan -t, biasanya dalam kombinasi -itdan Anda memiliki driver terminal ditambahkan, yang jika Anda berinteraksi dengan proses kemungkinan apa yang Anda inginkan. Ini pada dasarnya membuat wadah mulai terlihat seperti sesi koneksi terminal.


7
Ini harus menjadi jawaban teratas. Meskipun ini bukan yang paling teknis di sini, ini menjelaskan perilaku mendasar dari -itbendera.
Kris Khaira

1
Setuju dengan Kris. Saya membaca jawaban yang lain dan masih benar-benar bingung. Jawaban ini membersihkannya.
Ben Lee

4
Ya, mungkin perlu disebutkan bahwa "TTY" itu sendiri adalah akronim yang berasal dari kata "teletypewriter" (AKA "teleprinter") yang merupakan nama perangkat yang memungkinkan Anda mengetik teks dan mengirimnya dalam waktu yang sama - seperti telepon untuk teks ;-) Cobalah docker run -i ubuntudan docker run -it ubuntuAnda akan segera melihat perbedaannya. "-i" memungkinkan Anda untuk membuat wadah menunggu interaksi dari host tetapi interaksi sebenarnya dari konsol (terminal) dimungkinkan setelah Anda "mengalokasikan driver tty" dengan flag "-t".
Zegar

Bisakah saya memulai tty di dalam buruh pelabuhan? Saya memiliki beberapa aplikasi yang berhenti bekerja dengan saya tidak menjalankan buruh pelabuhan dengan -t, tetapi saya tidak dapat memodifikasi perintah mulai buruh pelabuhan dalam produksi. Jadi saya perlu membuat aplikasi berpikir itu dimulai dengan -t.
mvorisek

98

Jawaban terlambat, tetapi mungkin membantu seseorang

docker run/exec -iakan menghubungkan STDIN dari perintah di dalam wadah ke STDIN docker run/execitu sendiri.

Begitu

  • docker run -i alpine catmemberi Anda garis kosong menunggu input. Ketik "halo" Anda mendapatkan gema "halo". Kontainer tidak akan keluar sampai Anda mengirim CTRL+ Dkarena proses utama catsedang menunggu input dari aliran tak terbatas yang merupakan input terminal dari docker run.
  • Di sisi lain echo "hello" | docker run -i alpine catakan mencetak "halo" dan segera keluar karena catpemberitahuan bahwa aliran input telah berakhir dan berakhir dengan sendirinya.

Jika Anda mencoba docker pssetelah Anda keluar dari salah satu di atas, Anda tidak akan menemukan wadah berjalan. Dalam kedua kasus, catitu sendiri telah berakhir, sehingga buruh pelabuhan telah mengakhiri wadah.

Sekarang untuk "-t", ini memberitahu proses utama di dalam docker bahwa inputnya adalah perangkat terminal.

Begitu

  • docker run -t alpine catakan memberi Anda baris kosong, tetapi jika Anda mencoba mengetik "halo", Anda tidak akan mendapatkan gema. Ini karena saat catterhubung ke input terminal, input ini tidak terhubung ke input Anda. "Halo" yang Anda ketikkan tidak mencapai input cat. catsedang menunggu input yang tidak pernah tiba.
  • echo "hello" | docker run -t alpine catjuga akan memberi Anda garis kosong dan tidak akan keluar wadah CTRL- Dtetapi Anda tidak akan mendapatkan "halo" gema karena Anda tidak lulus-i

Jika Anda mengirim CTRL+ C, Anda mendapatkan shell Anda kembali, tetapi jika Anda mencoba docker pssekarang, Anda melihat catwadah masih berjalan. Ini karena catmasih menunggu aliran input yang tidak pernah ditutup. Saya belum menemukan penggunaan yang berguna untuk -tsendirian tanpa digabungkan dengan -i.

Sekarang, untuk -itbersama. Ini memberitahu kucing bahwa inputnya adalah terminal dan pada saat yang sama menghubungkan terminal ini ke input docker runyang merupakan terminal. docker run/execakan memastikan bahwa inputnya sendiri sebenarnya tty sebelum meneruskannya cat. Inilah sebabnya mengapa Anda akan mendapatkan input device is not a TTYjika Anda mencoba echo "hello" | docker run -it alpine catkarena dalam kasus ini, input docker runitu sendiri adalah pipa dari gema sebelumnya dan bukan terminal tempat docker rundieksekusi

Akhirnya, mengapa Anda harus lulus -tjika -iakan melakukan trik menghubungkan input Anda ke catinput? Ini karena perintah memperlakukan input secara berbeda jika terminal. Ini juga digambarkan dengan contoh

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -u root -pakan memberi Anda prompt kata sandi. Jika Anda mengetikkan kata sandi, karakter dicetak dengan jelas.
  • docker run -i alpine shakan memberi Anda garis kosong. Jika Anda mengetik perintah seperti lsAnda mendapatkan output, tetapi Anda tidak akan mendapatkan output berwarna atau prompt.

Dalam dua kasus terakhir, Anda mendapatkan perilaku ini karena mysqljuga shelltidak memperlakukan input sebagai tty dan karenanya tidak menggunakan perilaku spesifik tty seperti menutupi input atau mewarnai output.


6
Jawaban terbaik di sini yang benar-benar membuat saya mengerti apa sebenarnya -tdan -iopsi lakukan!
Ruslan Stelmachenko

1
Jawaban yang luar biasa yang mengantisipasi setiap pertanyaan yang saya miliki
James Machin

@Ahmed Ghonim, jawaban yang sangat bagus. Terima kasih. Tetapi tentang "Ini karena perintah memperlakukan input secara berbeda jika terminal", saya pikir itu salah ketik, kan? Seharusnya "Ini karena perintah memperlakukan input secara berbeda jika bukan terminal", kan?
tuq

@Ahmed Ghonim. Jelas. Tapi bagaimana dengan buruh pelabuhan run -a = stdin alpine cat?
HKIT

1
@HKIIT "-a = stdin" menempel aliran stdin ke wadah tetapi tanpa alokasi memori. Ini adalah flag -i yang mengalokasikan memori buffer dalam wadah untuk aliran stdin, maka deskripsi "Biarkan STDIN tetap terbuka meskipun tidak terpasang", ketika -i dilewatkan, memori dialokasikan untuk stdin terlepas dari flag attachment. Tanpa memori yang dialokasikan ini dibaca untuk stdin kosong / eof. Anda juga perlu memasukkan "-a = stdout" untuk melihat respons dari perintah cat misalnya: "buruh pelabuhan menjalankan -i -a = stdin -a = stdout alpine cat" ... tentu saja tidak perlu melakukan ini Anda bisa jalankan saja "buruh pelabuhan run -i alpine cat".
David D

71

The -tArgumen TIDAK didokumentasikan dengan baik, atau disebutkan oleh banyak orang sering, menurut pencarian Google.

Bahkan tidak muncul ketika Anda menampilkan daftar (apa yang seharusnya) semua argumen klien buruh pelabuhan dengan mengetik dockerdi Bash prompt (dengan versi terbaru 1.8.1).

Bahkan, jika Anda mencoba untuk mendapatkan bantuan khusus tentang argumen ini dengan mengetikkan docker -t --helpjika memberikan jawaban yang sangat samar-samar ini:

flag yang disediakan tetapi tidak didefinisikan: -t

Jadi, Anda tidak dapat disalahkan karena bingung dengan argumen ini!

Ada disebutkan dalam dokumentasi online Docker yang mengatakan itu untuk "Alokasikan pseudo-tty" dan sering digunakan dengan -i:

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

Saya melihatnya digunakan dalam dokumentasi untuk jwilder/nginx-proxywadah buruh pelabuhan hebat dengan cara berikut:

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

Dalam hal ini, yang dilakukannya adalah mengirim output ke tty 'virtual' (Bash command prompt / terminal) di dalam wadah buruh pelabuhan ini. Anda kemudian dapat melihat output ini dengan menjalankan perintah buruh pelabuhan di docker logs CONTAINERmana CONTAINERpasangan karakter pertama dari ID penampung ini. ID KONTAINER ini dapat ditemukan dengan mengetikdocker ps -a

Saya telah melihat -targumen ini disebutkan secara singkat di tautan berikut, di mana dikatakan

The -tdan -ibendera mengalokasikan pseudo-tty dan menjaga stdin terbuka bahkan jika tidak terpasang. Ini akan memungkinkan Anda untuk menggunakan wadah seperti VM tradisional selama bash prompt berjalan.

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

Saya harap ini membantu! Saya tidak yakin mengapa ini tidak didokumentasikan atau digunakan banyak. Mungkin ini eksperimental dan akan diimplementasikan sebagai fitur yang terdokumentasi di versi mendatang.


21
Dokumentasi muncul untuk docker run --help, bukan docker -t --help: -t, --tty=false Allocate a pseudo-TTY"
bskaggs

5

Yang saya tahu tentang -tini adalah sebagai berikut:

docker exec -ti CONTAINER bash- memungkinkan saya untuk "masuk" dalam wadah. Rasanya seperti ssh-ing (bukan).

Tetapi masalahnya adalah ketika saya ingin mengembalikan database.

Biasanya saya lakukan docker exec -ti mysql.5.7 mysql- Di sini saya menjalankan perintah mysql dalam wadah dan mendapatkan terminal interaktif.

Saya menambahkan <dump.sqlke perintah sebelumnya sehingga saya dapat mengembalikan db. Tetapi gagal dengan cannot enable tty mode on non tty input.

Menghapus bantuan -t. Masih tidak mengerti mengapa:

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

Yang terakhir berhasil. Semoga ini bisa membantu orang.


Bisakah saya memulai tty di dalam buruh pelabuhan? Saya memiliki beberapa aplikasi yang berhenti bekerja dengan saya tidak menjalankan buruh pelabuhan dengan -t, tetapi saya tidak dapat memodifikasi perintah mulai buruh pelabuhan dalam produksi. Jadi saya perlu membuat aplikasi berpikir itu dimulai dengan -t.
mvorisek

1

Di linux ketika Anda menjalankan perintah, Anda memerlukan terminal (tty) untuk menjalankannya.

Jadi ketika Anda ingin terhubung ke buruh pelabuhan (atau menjalankan perintah dalam wadah buruh pelabuhan), Anda harus memberikan opsi -t yang mempertimbangkan terminal di dalam wadah buruh pelabuhan.


0

Setiap proses memiliki tiga aliran data yaitu STDIN/ STDOUT/ STDERR. Ketika suatu proses berjalan dalam sebuah wadah, terminal default terhubung dengan aliran STDOUT dari proses yang berjalan dalam wadah. Karenanya semua aliran keluaran akan terlihat saat menjalankan docker runperintah di terminal. Tetapi jika Anda ingin memberikan input untuk proses yang berjalan dalam wadah maka Anda harus terhubung dengan saluran STDIN dari proses yang tidak secara default dan dilakukan dengandocker run -i perintah.

-t digunakan untuk operasi input interaktif / diformat.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.