Apa arti sebenarnya dari "perangkat input bukan TTY" dalam output "docker run"?

Ini adalah perintah yang berfungsi:

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

Ini adalah perintah yang merespons dengan pesan kesalahan:

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

Saya ingin mencari tahu persis apa yang terjadi di sini. Bukan hanya "hapus-t dan itu akan diperbaiki".

Aku tahu itu docker runini -t option singkatan dari "alokasikan pseudo-TTY", dan saya telah membaca ikhtisar sejarah tentang apa yang dimaksud dengan TTY, tapi itu tidak membantu saya memahami kontrak seperti apa yang dilanggar di sini.

Jawaban terlambat, tapi mungkin bisa membantu seseorang

docker run/exec -i akan menghubungkan stdin dari perintah di dalam wadah ke STDIN dari docker run/exec sendiri.

Jadi

  • docker run -i alpine cat memberi Anda baris kosong menunggu input. Ketik"halo " Anda mendapatkan gema"halo & quot;. Wadah tidak akan keluar sampai Anda mengirim CTRL + D karena proses utama cat sedang menunggu input dari aliran tak terbatas yang merupakan input terminal dari docker run.
  • Di sisi lain echo "hello" | docker run -i alpine cat akan mencetak & quot;halo& quot; dan keluar segera karena cat pemberitahuan bahwa aliran input telah berakhir dan berakhir sendiri.

Jika Anda mencoba docker ps setelah Anda keluar dari salah satu di atas, Anda tidak akan menemukan wadah yang sedang berjalan. Dalam kedua kasus, cat sendiri telah dihentikan, sehingga docker telah dihentikan wadah.

Sekarang untuk " - t", Ini memberi tahu proses utama di dalam docker bahwa inputnya adalah perangkat terminal.

Jadi

  • docker run -t alpine cat akan memberikan baris kosong, tetapi jika Anda mencoba untuk mengetik "halo", Anda tidak akan mendapatkan gema apapun. Hal ini karena sementara cat terhubung ke input terminal, input ini tidak terhubung ke input Anda. & Quot;halo & quot; yang anda ketik tidak mencapai input cat. cat sedang menunggu masukan yang tidak pernah datang.
  • echo "hello" | docker run -t alpine cat juga akan memberi Anda garis kosong dan tidak akan keluar dari wadah pada CTRL-D tetapi Anda tidak akan mendapatkan gema"halo & quot; karena Anda tidak lulus -i

Jika Anda mengirim CTRL + C, Anda mendapatkan shell Anda kembali, tetapi jika Anda mencoba docker ps sekarang, Anda melihat cat kontainer masih berjalan. Hal ini karena cat masih menunggu aliran input yang tidak pernah ditutup. Saya belum menemukan penggunaan yang berguna untuk -t sendiri tanpa digabungkan dengan -i.

Sekarang, untuk -it bersama-sama. Ini memberi tahu cat bahwa inputnya adalah terminal dan pada saat yang sama menghubungkan terminal ini ke input docker run yang merupakan terminal. docker run/exec akan memastikan bahwa inputnya sendiri sebenarnya adalah tty sebelum meneruskannya ke cat. Inilah sebabnya mengapa Anda akan mendapatkan input device is not a TTY jika Anda mencoba echo "hello" | docker run -it alpine cat karena dalam hal ini, Masukan dari docker run itu sendiri adalah pipa dari gema sebelumnya dan bukan terminal di mana docker run dieksekusi

Akhirnya, mengapa Anda harus lulus -t jika -i akan melakukan trik menghubungkan input Anda ke catmasukan? Ini karena perintah memperlakukan input secara berbeda jika itu adalah terminal. Ini juga paling baik diilustrasikan dengan contoh

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p akan memberi Anda prompt kata sandi. Jika Anda mengetik kata sandi, karakter dicetak dengan jelas.
  • docker run -i alpine sh akan memberi Anda garis kosong. Jika Anda mengetik perintah seperti ls Anda mendapatkan output, tetapi Anda tidak akan mendapatkan output prompt atau berwarna.

Dalam dua kasus terakhir, Anda mendapatkan perilaku ini karena mysql serta shell tidak memperlakukan input sebagai tty dan dengan demikian tidak menggunakan perilaku spesifik tty seperti menutupi input atau mewarnai output.

Jawaban ini membantu saya untuk membungkus kepala saya sekitar:

  • secara default (tanpa keduanya -i nor -t opsi) wadah Docker hanya mengirimkan outputnya toSTDOUT,
  • dengan -i opsi datang koneksi ke STDIN,
  • -t opsi menarik driver antarmuka terminal, yang berfungsi di atas STDIN/STDOUT. Dan ketika driver terminal ditarik, komunikasi dengan wadah harus sesuai dengan protokol antarmuka terminal. Piping string tidak.

Tty menunjukkan Anda memiliki terminal, sesuatu yang akan disediakan oleh xterm atau salah satu dari banyak antarmuka baris perintah linux. Ini membutuhkan keyboard dan antarmuka output teks yang terkait dengannya. Alasan khas untuk menginginkan ini adalah untuk dukungan output teks warna, penanganan berbagai kombinasi tombol (seperti tombol panah), dan kemampuan untuk memindahkan kursor di sekitar layar.

Ketika Anda pipa perintah ke docker seperti Anda echo contoh menunjukkan, pipa itu adalah input, dan pipa itu tidak memiliki antarmuka tty, itu hanya aliran teks. Mencoba membuat tty dengan itu akan gagal seperti yang ditunjukkan oleh pesan kesalahan.

Bisakah saya memulai tty di dalam docker? Saya memiliki beberapa aplikasi yang berhenti bekerja 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’.

Ini tidak berlebihan, docker dapat membuat TTY tanpa melampirkan apa pun padanya. Output Anda akan memiliki karakter untuk warna, dll, tetapi output terminal Anda tidak akan disalurkan ke input wadah. Jadi karakter yang anda ketik akan diantrekan untuk perintah berikutnya yang anda jalankan setelah perintah docker keluar.