ทั้งสองจะสามารถรันคำสั่งในคอนเทนเนอร์ได้ ทั้งสองสามารถถอดภาชนะออกได้
ดังนั้นความแตกต่างที่แท้จริงระหว่าง docker exec และ dockerแนบคืออะไร?
ทั้งสองจะสามารถรันคำสั่งในคอนเทนเนอร์ได้ ทั้งสองสามารถถอดภาชนะออกได้
ดังนั้นความแตกต่างที่แท้จริงระหว่าง docker exec และ dockerแนบคืออะไร?
มี commit PR ซึ่งเพิ่มลงในเอกสาร:
หมายเหตุ: คำสั่งนี้ (
attach
) ไม่ได้มีไว้สำหรับเรียกใช้กระบวนการใหม่ในคอนเทนเนอร์ ดู:docker exec
คำตอบของ "Docker วิธีรับ bash\ssh ภายในคอนเทนเนอร์ที่รัน (run -d
)?" แสดงให้เห็นถึงความแตกต่าง:
(นักเทียบท่า >= 1.3) หากเราใช้
docker attach
เราสามารถ ใช้เชลล์เพียงอินสแตนซ์เดียว.
ดังนั้นหากเราต้องการเปิดเทอร์มินัลใหม่ด้วยอินสแตนซ์ใหม่ของเชลล์คอนเทนเนอร์ เราเพียงแค่ต้องเรียกใช้docker exec
หากคอนเทนเนอร์นักเทียบท่าเริ่มทำงานโดยใช้คำสั่ง
/bin/bash
คุณสามารถเข้าถึงได้โดยใช้ไฟล์แนบ หากไม่เป็นเช่นนั้น คุณจะต้อง ดำเนินการ คำสั่งเพื่อสร้างอินสแตนซ์ bash ภายในคอนเทนเนอร์โดยใช้exec
ตามที่กล่าวไว้ในปัญหานี้:
- การแนบไม่ได้มีไว้สำหรับการเรียกใช้สิ่งพิเศษในคอนเทนเนอร์ แต่สำหรับการแนบกับกระบวนการที่กำลังรันอยู่
- "
docker exec
" มีไว้สำหรับเรียกใช้สิ่งใหม่ๆ ในคอนเทนเนอร์ที่เริ่มต้นแล้วโดยเฉพาะ ไม่ว่าจะเป็นเชลล์หรือกระบวนการอื่นๆ
ปัญหาเดียวกันนี้เพิ่ม:
แม้ว่า
attach
จะตั้งชื่อได้ไม่ดีนัก โดยเฉพาะอย่างยิ่งเนื่องจากคำสั่ง LXClxc-attach
(ซึ่งคล้ายกับdocker exec <container> /bin/sh
มากกว่า แต่เฉพาะเจาะจงกับ LXC) แต่ก็มีวัตถุประสงค์เฉพาะในการแนบคุณเข้ากับกระบวนการที่ Docker เริ่มต้นอย่างแท้จริง
ขึ้นอยู่กับ กระบวนการที่เป็นพฤติกรรมอาจแตกต่างกัน เช่น การแนบกับ/bin/bash
จะทำให้คุณได้รับเชลล์ แต่การแนบกับเซิร์ฟเวอร์ Redis จะเหมือนกับว่าคุณเพิ่งเริ่ม Redis โดยตรงโดยไม่ต้อง daemonizing
เมื่อคอนเทนเนอร์เริ่มใช้ /bin/bash คอนเทนเนอร์นั้นจะกลายเป็นคอนเทนเนอร์ PID 1 และนักเทียบท่าจะใช้ในการเข้าไปภายใน PID 1 ของคอนเทนเนอร์ ดังนั้น นักเทียบท่าแนบ ‹ คอนเทนเนอร์-id > จะนำคุณเข้าไปในเทอร์มินัล bash เนื่องจากเป็น PID 1 ตามที่เรากล่าวไว้ในขณะที่เริ่มต้นคอนเทนเนอร์ การออกจากคอนเทนเนอร์จะหยุดคอนเทนเนอร์
ในขณะที่คำสั่ง docker exec คุณสามารถระบุเชลล์ที่คุณต้องการป้อนได้ มันจะไม่นำคุณไปที่ PID 1 ของคอนเทนเนอร์ มันจะสร้างกระบวนการใหม่สำหรับการทุบตี นักเทียบท่า exec -it ‹ คอนเทนเนอร์-id > ทุบตี การออกจากคอนเทนเนอร์จะไม่ทำให้คอนเทนเนอร์หยุดทำงาน
คุณยังสามารถใช้ nsenter เพื่อเข้าไปในคอนเทนเนอร์ได้ nsenter -m -u -n -p -i -t ‹ pid ของคอนเทนเนอร์ > คุณสามารถค้นหา PID ของคอนเทนเนอร์ได้โดยใช้: docker inspect ‹ container-id > | grep PID
หมายเหตุ: หากคุณเริ่มต้นคอนเทนเนอร์ด้วยแฟล็ก -d การออกจากคอนเทนเนอร์จะไม่หยุดคอนเทนเนอร์ ไม่ว่าคุณจะใช้การแนบหรือ exec เพื่อเข้าไปข้างใน
nsenter
คุณช่วยอธิบายรายละเอียดได้ไหม? การอธิบายตัวเลือกจะเป็นไปตามลำดับ ทำไมไม่ใส่เนมสเปซทั้งหมด? ทำไมคนเหล่านี้โดยเฉพาะ?
- person x-yuri; 29.06.2019
ดังที่ Michael Sun ระบุไว้ในคำตอบของเขา
docker exec
ดำเนินการคำสั่งใหม่ / สร้างกระบวนการใหม่ในสภาพแวดล้อมของคอนเทนเนอร์ ในขณะที่docker attach
เพียงเชื่อมต่ออินพุต/เอาต์พุต/ข้อผิดพลาดมาตรฐานของกระบวนการหลัก (ด้วย PID 1) ภายในคอนเทนเนอร์กับอินพุต/เอาต์พุต/ข้อผิดพลาดมาตรฐานที่สอดคล้องกันของเทอร์มินัลปัจจุบัน ( เทอร์มินัลที่คุณใช้เพื่อรันคำสั่ง)
คำตอบของฉันจะเน้นไปที่การให้คุณตรวจสอบข้อความข้างต้นและเข้าใจได้ชัดเจนยิ่งขึ้น
เปิดหน้าต่างเทอร์มินัลแล้วรันคำสั่ง docker run -itd --name busybox busybox /bin/sh
คำสั่งจะดึงรูปภาพ busybox
หากยังไม่มี จากนั้นจะสร้างคอนเทนเนอร์ชื่อ busybox
โดยใช้อิมเมจนี้
คุณสามารถตรวจสอบสถานะของคอนเทนเนอร์ของคุณได้โดยการรันคำสั่ง docker ps -a | grep busybox
หากคุณรัน docker top busybox
คุณจะเห็นผลลัพธ์ดังนี้
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
แน่นอนว่า PID
, PPID
และค่าอื่นๆ จะแตกต่างออกไปในกรณีของคุณ คุณสามารถใช้เครื่องมือและยูทิลิตีอื่นๆ เช่น pstree
, top
, htop
เพื่อดูรายการ PID
และ PPID
PID
และ PPID
หมายถึงรหัสกระบวนการและรหัสกระบวนการหลัก กระบวนการเริ่มต้นเมื่อเราสร้างและเริ่มคอนเทนเนอร์ด้วยคำสั่ง /bin/sh
ตอนนี้ให้รันคำสั่ง docker attach busybox
ซึ่งจะแนบสตรีมอินพุต/เอาต์พุต/ข้อผิดพลาดมาตรฐานของคอนเทนเนอร์เข้ากับเทอร์มินัลของคุณ
หลังจากแนบคอนเทนเนอร์แล้ว ให้สร้างเซสชันเชลล์โดยรันคำสั่ง sh
กด CTRL-p CTRL-q
ลำดับ การดำเนินการนี้จะแยกเทอร์มินัลออกจากคอนเทนเนอร์และจะทำให้คอนเทนเนอร์ทำงานต่อไป หากตอนนี้คุณรัน docker top busybox
คุณจะเห็นสองกระบวนการในรายการ
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
root 7737 7469 0 11:43 pts/0 00:00:00 sh
แต่ PPID
ของทั้งสองกระบวนการจะแตกต่างกัน อันที่จริงแล้ว PPID
ของกระบวนการที่สองจะเหมือนกับ PID
ของกระบวนการแรก กระบวนการแรกทำหน้าที่เป็นกระบวนการหลักสำหรับเซสชันเชลล์ที่เราเพิ่งสร้างขึ้น
ตอนนี้รัน docker exec -it busybox sh
เมื่อเข้าไปในคอนเทนเนอร์แล้ว ให้ตรวจสอบรายการกระบวนการที่ทำงานอยู่สำหรับคอนเทนเนอร์ busybox
ในหน้าต่างเทอร์มินัลอื่นโดยรันคำสั่ง docker top busybox
คุณควรเห็นสิ่งนี้
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
root 7737 7469 0 11:43 pts/0 00:00:00 sh
root 7880 7451 0 11:45 pts/1 00:00:00 sh
PPID
ของกระบวนการที่หนึ่งและสามจะเหมือนกัน ซึ่งยืนยันว่า docker exec
สร้างกระบวนการใหม่ในสภาพแวดล้อมของคอนเทนเนอร์ ในขณะที่ docker attach
เพียงเชื่อมต่ออินพุต/เอาต์พุต/ข้อผิดพลาดมาตรฐานของกระบวนการหลักภายในคอนเทนเนอร์กับอินพุต/เอาต์พุตมาตรฐานที่สอดคล้องกัน ข้อผิดพลาดของเทอร์มินัลปัจจุบัน
Docker exec ดำเนินการคำสั่งใหม่ / สร้างกระบวนการใหม่ในสภาพแวดล้อมของคอนเทนเนอร์ในขณะที่นักเทียบท่าแนบเพียงเชื่อมต่ออินพุต / เอาท์พุต / ข้อผิดพลาดมาตรฐานของกระบวนการหลัก (ด้วย PID 1) ภายในคอนเทนเนอร์กับอินพุต / เอาท์พุต / ข้อผิดพลาดมาตรฐานที่สอดคล้องกันของกระแส เทอร์มินัล (เทอร์มินัลที่คุณใช้เพื่อรันคำสั่ง)
คอนเทนเนอร์เป็นสภาพแวดล้อมแบบแยกส่วน โดยมีกระบวนการบางอย่างทำงานอยู่ในสภาพแวดล้อม โดยเฉพาะอย่างยิ่ง คอนเทนเนอร์มีพื้นที่ระบบไฟล์และพื้นที่ PID ของตัวเองที่แยกออกจากโฮสต์และคอนเทนเนอร์อื่นๆ เมื่อคอนเทนเนอร์เริ่มต้นโดยใช้ “docker run –it …” กระบวนการหลักจะมี pseudo-tty และ STDIN เก็บไว้เปิดอยู่ เมื่อเชื่อมต่อในโหมด tty คุณสามารถแยกออกจากคอนเทนเนอร์ได้ (และปล่อยให้คอนเทนเนอร์ทำงานต่อไป) โดยใช้ลำดับคีย์ที่กำหนดค่าได้ ลำดับเริ่มต้นคือ CTRL-p CTRL-q คุณกำหนดค่าลำดับคีย์โดยใช้ตัวเลือก --detach-keys หรือไฟล์การกำหนดค่า คุณสามารถแนบกลับเข้ากับคอนเทนเนอร์ที่แยกออกมาโดยแนบนักเทียบท่าได้
Docker exec เพิ่งเริ่มกระบวนการใหม่ภายในสภาพแวดล้อมของคอนเทนเนอร์ ซึ่งก็คือเป็นของพื้นที่ PID ของคอนเทนเนอร์
ตัวอย่างเช่น หากคุณเริ่มคอนเทนเนอร์โดยใช้ "docker run –dit XXX /bin/bash" คุณสามารถแนบไปกับคอนเทนเนอร์ (กระบวนการหลักของ) โดยใช้เทอร์มินัลสองเครื่องที่แตกต่างกัน ขณะที่คุณกำลังป้อนข้อมูลในเทอร์มินัลหนึ่ง คุณจะเห็นได้ว่าปรากฏในอีกเทอร์มินัลหนึ่ง เนื่องจากทั้งสองเทอร์มินัลเชื่อมต่อกับ tty เดียวกัน โปรดใช้ความระมัดระวังว่าขณะนี้คุณอยู่ในกระบวนการหลักของคอนเทนเนอร์ หากคุณพิมพ์ "exit" คุณจะออกจากคอนเทนเนอร์ (โปรดใช้ความระมัดระวังโดยใช้กุญแจในการแยกออก) และคุณจะเห็น ออกจากเทอร์มินัลทั้งสองแล้ว แต่ถ้าคุณเรียกใช้ “docker exec –it XXX /bin/bash” ในสองเทอร์มินัล คุณได้เริ่มต้นกระบวนการใหม่สองกระบวนการภายในคอนเทนเนอร์ และกระบวนการเหล่านั้นไม่เกี่ยวข้องกันและกับกระบวนการหลัก และคุณสามารถออกจากกระบวนการเหล่านั้นได้อย่างปลอดภัย .