ตัวเลือกนี้จะทำอะไรกันแน่? ฉันอ่าน TTY มากและยังคงสับสนอยู่ ผมเล่นไปรอบ ๆ ด้วยไม่ได้มี-t
เพียงและดูเหมือนว่าโปรแกรมที่คาดหวังว่าผู้ใช้ป้อนโยนความผิดพลาดโดยไม่ต้อง-i
-t
ทำไมการเปิดใช้งานหลอก -TTY จึงสำคัญ?
ตัวเลือกนี้จะทำอะไรกันแน่? ฉันอ่าน TTY มากและยังคงสับสนอยู่ ผมเล่นไปรอบ ๆ ด้วยไม่ได้มี-t
เพียงและดูเหมือนว่าโปรแกรมที่คาดหวังว่าผู้ใช้ป้อนโยนความผิดพลาดโดยไม่ต้อง-i
-t
ทำไมการเปิดใช้งานหลอก -TTY จึงสำคัญ?
คำตอบ:
-t
ตัวเลือกที่จะไปว่า Unix / Linux จัดการเข้า terminal ในอดีตเทอร์มินัลเป็นการเชื่อมต่อแบบอนุกรมหลังจากนั้นเป็นการเชื่อมต่อแบบโมเด็ม เหล่านี้มีไดรเวอร์อุปกรณ์ทางกายภาพ (เป็นอุปกรณ์จริง) เมื่อเครือข่ายทั่วไปเข้ามาใช้ไดรเวอร์ pseudo-terminal ได้รับการพัฒนา นี่เป็นเพราะมันสร้างการแยกระหว่างการทำความเข้าใจความสามารถของเทอร์มินัลที่สามารถใช้งานได้โดยไม่จำเป็นต้องเขียนลงในโปรแกรมของคุณโดยตรง (อ่าน man pages on stty
, curses
)
ดังนั้นด้วยการที่เป็นพื้นหลังให้เรียกใช้คอนเทนเนอร์โดยไม่มีตัวเลือกและโดยค่าเริ่มต้นคุณจะมีสตรีม stdout (ดังนั้นใช้docker run | <cmd>
งานได้); ทำงานด้วย-i
และคุณจะได้รับกระแส stdin เพิ่ม ( <cmd> | docker run -i
ทำงานได้ดี); ใช้งาน-t
โดยทั่วไปจะเป็นการรวมกัน-it
และคุณได้เพิ่มไดรเวอร์เทอร์มินัลซึ่งหากคุณมีปฏิสัมพันธ์กับกระบวนการน่าจะเป็นสิ่งที่คุณต้องการ โดยพื้นฐานแล้วทำให้การเริ่มต้นคอนเทนเนอร์ดูเหมือนเซสชันการเชื่อมต่อเทอร์มินัล
docker run -i ubuntu
และdocker run -it ubuntu
คุณจะเห็นความแตกต่างทันที "-i" ช่วยให้คุณสร้างคอนเทนเนอร์เพื่อรอการโต้ตอบจากโฮสต์ แต่การโต้ตอบจริงจากคอนโซล (เทอร์มินัล) เป็นไปได้หลังจากที่คุณ "จัดสรรไดรเวอร์ tty" ด้วยแฟล็ก "-t"
-t
แต่ฉันไม่สามารถแก้ไขคำสั่ง docker start ในการผลิตได้ -t
ดังนั้นผมจึงต้องการที่จะทำให้แอปคิดว่ามันเริ่มต้นด้วย
ตอบช้า แต่อาจช่วยใครซักคน
docker run/exec -i
จะเชื่อมต่อ STDIN ของคำสั่งภายในคอนเทนเนอร์กับ STDIN ของdocker run/exec
ตัวเอง
ดังนั้น
docker run -i alpine cat
ช่วยให้คุณมีบรรทัดว่างรอการป้อนข้อมูล พิมพ์ "สวัสดี" คุณจะได้รับเสียงสะท้อน "สวัสดี" ภาชนะที่จะไม่ออกจนกว่าคุณจะส่งCTRL+ Dเพราะกระบวนการหลักคือการรอคอยสำหรับการป้อนข้อมูลจากกระแสอนันต์ที่มีการป้อนข้อมูลที่ขั้วของcat
docker run
echo "hello" | docker run -i alpine cat
จะพิมพ์ "hello" และออกทันทีเพราะcat
สังเกตว่ากระแสข้อมูลได้สิ้นสุดลงและยุติตัวเองหากคุณลองdocker ps
หลังจากออกจากข้อใดข้อหนึ่งข้างต้นคุณจะไม่พบคอนเทนเนอร์ที่ใช้งานอยู่ ในทั้งสองกรณีcat
ตัวเองได้ยกเลิกดังนั้นนักเทียบท่าได้ยกเลิกภาชนะ
ตอนนี้สำหรับ "-t" นี่จะบอกกระบวนการหลักภายในตัวเทียบท่าว่าอินพุตเป็นอุปกรณ์เทอร์มินัล
ดังนั้น
docker run -t alpine cat
จะให้บรรทัดว่าง แต่ถ้าคุณลองพิมพ์ "hello" คุณจะไม่ได้เสียงสะท้อนใด ๆ นี่เป็นเพราะขณะที่cat
เชื่อมต่อกับอินพุตเทอร์มินัลอินพุตนี้ไม่ได้เชื่อมต่อกับอินพุตของคุณ "Hello" cat
ที่คุณพิมพ์ไม่ถึงการป้อนข้อมูลของ cat
กำลังรออินพุตที่ไม่เคยมาถึงecho "hello" | docker run -t alpine cat
จะให้บรรทัดว่างกับคุณและจะไม่ออกจากคอนเทนเนอร์ในCTRL- Dแต่คุณจะไม่ได้รับเสียงสะท้อน "สวัสดี" เพราะคุณไม่ผ่าน-i
ถ้าคุณส่งCTRL+ Cคุณจะได้เปลือกของคุณกลับมา แต่ถ้าคุณลองdocker ps
ตอนนี้คุณจะเห็นว่าcat
คอนเทนเนอร์ยังคงทำงานอยู่ ทั้งนี้เป็นเพราะcat
ยังคงรอสตรีมอินพุตที่ไม่เคยปิด ฉันไม่ได้พบการใช้ประโยชน์ใด ๆ สำหรับคนเดียวโดยไม่ต้องถูกรวมกับ-t
-i
ตอนนี้เพื่อ-it
ร่วมกัน สิ่งนี้บอกกับ cat ว่าอินพุตเป็นเทอร์มินัลและในเวลาเดียวกันเชื่อมต่อเทอร์มินัลนี้กับอินพุตdocker run
ซึ่งเป็นเทอร์มินัล docker run/exec
จะให้แน่ใจว่าการป้อนข้อมูลของตัวเองในความเป็นจริง TTY cat
ก่อนที่จะผ่านไปยัง นี่คือเหตุผลที่คุณจะได้รับinput device is not a TTY
ถ้าคุณลองecho "hello" | docker run -it alpine cat
เพราะในกรณีนี้อินพุตของdocker run
ตัวเองเป็นไพพ์จากเสียงก้องก่อนหน้าและไม่ใช่เทอร์มินัลที่docker run
ถูกเรียกใช้งาน
ในที่สุดทำไมคุณจะต้องผ่าน-t
หาก-i
จะทำเคล็ดลับในการเชื่อมต่ออินพุตของคุณกับcat
อินพุตของ นี่เป็นเพราะคำสั่งจัดการอินพุตต่างกันถ้ามันเป็นเทอร์มินัล นี่เป็นตัวอย่างที่ดีที่สุด
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -u root -p
จะให้พรอมต์รหัสผ่านแก่คุณ หากคุณพิมพ์รหัสผ่านอักขระจะถูกพิมพ์อย่างชัดเจนdocker run -i alpine sh
จะให้บรรทัดที่ว่างกับคุณ หากคุณพิมพ์คำสั่งเช่นls
คุณได้รับผลลัพธ์ แต่คุณจะไม่ได้รับพรอมต์หรือสีที่ส่งออกในสองกรณีสุดท้ายคุณจะได้รับพฤติกรรมนี้เพราะmysql
เช่นเดียวกับที่shell
ไม่ได้รับการรักษาอินพุตเป็น tty และดังนั้นจึงไม่ได้ใช้พฤติกรรมที่เฉพาะเจาะจงเช่น tty เช่นปิดบังอินพุตหรือระบายสีเอาท์พุท
-t
และ-i
ตัวเลือกทำจริงๆ!
-t
โต้แย้งไม่ได้เอกสารดีหรือกล่าวถึงโดยคนจำนวนมากมักจะตามการค้นหาของ Google
มันจะไม่ปรากฏขึ้นเมื่อคุณแสดงรายการข้อโต้แย้งไคลเอนต์นักเทียบท่าทั้งหมดโดยพิมพ์docker
ที่ Bash prompt (ด้วยเวอร์ชันล่าสุดของ 1.8.1)
ในความเป็นจริงถ้าคุณพยายามขอความช่วยเหลือเฉพาะเกี่ยวกับเรื่องนี้โดยการพิมพ์docker -t --help
ถ้าให้คำตอบที่คลุมเครืออย่างน่าอัศจรรย์นี้:
ให้ไว้ แต่ไม่ได้กำหนด: -t
ดังนั้นคุณไม่สามารถถูกตำหนิว่าสับสนกับเรื่องนี้!
มีการกล่าวถึงในเอกสารออนไลน์ของ Docker ซึ่งกล่าวว่าเป็นการ "จัดสรรหลอก" และมักใช้กับ-i
:
https://docs.docker.com/reference/run/
ฉันเห็นมันใช้ในเอกสารประกอบสำหรับตัวjwilder/nginx-proxy
เทียบท่าที่ยอดเยี่ยมด้วยวิธีต่อไปนี้:
docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx
ในกรณีนี้สิ่งที่มันคือการส่งออกไปยัง 'เสมือน' tty (พรอมต์คำสั่ง / ขั้ว / Bash) ภายในคอนเทนเนอร์นักเทียบท่านี้ จากนั้นคุณสามารถเห็นเอาต์พุตนี้โดยการรันคำสั่ง docker docker logs CONTAINER
โดยที่CONTAINER
เป็นคู่แรกของอักขระของ ID คอนเทนเนอร์นี้ รหัสคอนเทนเนอร์นี้สามารถพบได้โดยการพิมพ์docker ps -a
ฉันเคยเห็น-t
อาร์กิวเมนต์นี้พูดถึงสั้น ๆ ในลิงค์ต่อไปนี้ที่มันบอกว่า
-t
และ-i
ธงจัดสรรหลอก TTY และให้ stdin เปิดแม้ว่าจะไม่ได้แนบมา สิ่งนี้จะช่วยให้คุณใช้คอนเทนเนอร์เช่น VM ดั้งเดิมได้ตราบใดที่พรอมต์ bash กำลังทำงาน
https://coreos.com/os/docs/latest/getting-started-with-docker.html
ฉันหวังว่านี่จะช่วยได้! ฉันไม่แน่ใจว่าทำไมสิ่งนี้จึงไม่ถูกบันทึกหรือใช้มากนัก อาจเป็นการทดลองและจะนำไปใช้เป็นคุณลักษณะที่บันทึกไว้ในเวอร์ชันที่กำลังจะมาถึง
docker run --help
ไม่ใช่docker -t --help
: -t, --tty=false Allocate a pseudo-TTY
"
สิ่งที่ฉันรู้เกี่ยวกับ-t
สิ่งต่อไปนี้:
docker exec -ti CONTAINER bash
- ช่วยให้ฉัน "เข้าสู่ระบบ" ในภาชนะ มันรู้สึกเหมือน ssh-ing (ไม่ใช่)
แต่ปัญหาคือเมื่อฉันต้องการคืนค่าฐานข้อมูล
ฉันมักจะทำdocker exec -ti mysql.5.7 mysql
- ที่นี่ฉันรันคำสั่ง mysql ในภาชนะและรับ terminal โต้ตอบ
ฉันเพิ่ม<dump.sql
ไปยังคำสั่งก่อนหน้าเพื่อให้ฉันสามารถคืนค่า db cannot enable tty mode on non tty input
แต่ก็ล้มเหลวด้วย
การถอด-t
ช่วย ยังไม่เข้าใจว่าทำไม:
docker exec -i mysql.5.7 mysql < dump.sql
อันสุดท้ายใช้ได้ผล หวังว่านี่จะช่วยให้ผู้คน
-t
แต่ฉันไม่สามารถแก้ไขคำสั่ง docker start ในการผลิตได้ -t
ดังนั้นผมจึงต้องการที่จะทำให้แอปคิดว่ามันเริ่มต้นด้วย
ใน linux เมื่อคุณรันคำสั่งคุณจำเป็นต้องมีเทอร์มินัล (tty) เพื่อเรียกใช้งาน
ดังนั้นเมื่อคุณต้องการที่จะเชื่อมต่อกับนักเทียบท่า (หรือเรียกใช้คำสั่งในคอนเทนเนอร์นักเทียบท่า) คุณจะต้องให้ตัวเลือก -t ซึ่งใช้ในการพิจารณาของสถานีภายในภาชนะที่นักเทียบท่า
STDIN/ STDOUT/ STDERR
ทุกขั้นตอนมีสามกระแสข้อมูลคือ เมื่อกระบวนการทำงานในคอนเทนเนอร์โดยเทอร์มินัลเริ่มต้นจะเชื่อมต่อกับสตรีม STDOUT ของกระบวนการที่ทำงานในคอนเทนเนอร์ ดังนั้นสตรีมเอาต์พุตทั้งหมดจะมองเห็นได้ในขณะที่รันdocker run
คำสั่งในเทอร์มินัล แต่ถ้าคุณต้องการป้อนข้อมูลให้กับกระบวนการที่กำลังทำงานอยู่ในคอนเทนเนอร์คุณต้องเชื่อมต่อกับช่อง STDIN ของกระบวนการซึ่งไม่ได้เป็นค่าเริ่มต้นและทำด้วยdocker run -i
คำสั่ง
-t
ใช้สำหรับการป้อนข้อมูลแบบโต้ตอบ / จัดรูปแบบ
-it
แนะเทียบท่าที่จะจัดสรรหลอก TTY เชื่อมต่อกับ stdin คอนเทนเนอร์ที่การสร้างเปลือกทุบตีโต้ตอบในภาชนะ
--interactive
, -i
false
ให้ STDIN เปิดอยู่แม้ว่าจะไม่ได้เชื่อมต่อก็ตาม
--tty
, -t
false
จัดสรรหลอก TTY
-it
ธง