ฉันพยายามทำความเข้าใจเหตุผลที่แท้จริงของการติดตั้งdocker.sock
ในdocker-compose.yml
ไฟล์ มีไว้สำหรับการค้นหาอัตโนมัติหรือไม่
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ฉันพยายามทำความเข้าใจเหตุผลที่แท้จริงของการติดตั้งdocker.sock
ในdocker-compose.yml
ไฟล์ มีไว้สำหรับการค้นหาอัตโนมัติหรือไม่
volumes:
- /var/run/docker.sock:/var/run/docker.sock
คำตอบ:
docker.sock
คือซ็อกเก็ต UNIX ที่ Docker daemon กำลังฟังอยู่ เป็นจุดเริ่มต้นหลักสำหรับ Docker API นอกจากนี้ยังสามารถเป็นซ็อกเก็ต TCP แต่โดยค่าเริ่มต้นเพื่อเหตุผลด้านความปลอดภัย Docker จะใช้ค่าเริ่มต้นของซ็อกเก็ต UNIX
ไคลเอ็นต์ Docker cli ใช้ซ็อกเก็ตนี้เพื่อดำเนินการคำสั่ง Docker ตามค่าเริ่มต้น คุณสามารถลบล้างการตั้งค่าเหล่านี้ได้เช่นกัน
อาจมีสาเหตุหลายประการที่ทำให้คุณต้องติดตั้งซ็อกเก็ต Docker ภายในคอนเทนเนอร์ เช่นเดียวกับการเปิดตัวคอนเทนเนอร์ใหม่จากภายในคอนเทนเนอร์อื่น หรือเพื่อวัตถุประสงค์ในการค้นหาและบันทึกบริการอัตโนมัติ สิ่งนี้จะเพิ่มพื้นผิวการโจมตีดังนั้นคุณควรระวังหากคุณติดตั้งซ็อกเก็ตนักเทียบท่าไว้ในคอนเทนเนอร์ซึ่งมีรหัสที่เชื่อถือได้ทำงานอยู่ภายในคอนเทนเนอร์นั้นมิฉะนั้นคุณสามารถบุกรุกโฮสต์ของคุณที่กำลังเรียกใช้ Docker daemon ได้เนื่องจากโดยค่าเริ่มต้น Docker จะเปิดใช้งานคอนเทนเนอร์ทั้งหมดในฐานะรูท
ซ็อกเก็ต Docker มีกลุ่มนักเทียบท่าในการติดตั้งส่วนใหญ่ดังนั้นผู้ใช้ภายในกลุ่มนั้นจึงสามารถเรียกใช้คำสั่งนักเทียบท่ากับซ็อกเก็ตนักเทียบท่าโดยไม่ได้รับอนุญาตจากรูท แต่คอนเทนเนอร์นักเทียบท่าจริงยังคงได้รับสิทธิ์รูทเนื่องจากนักเทียบท่าดีมอนทำงานเป็นรูทอย่างมีประสิทธิภาพ (ต้องได้รับอนุญาตรูทเพื่อเข้าถึงเนมสเปซและ cgroups) .
ฉันหวังว่ามันจะตอบคำถามของคุณ
ข้อมูลเพิ่มเติม: https://docs.docker.com/engine/reference/commandline/dockerd/#examples
/var/run/docker.sock
ภายในคอนเทนเนอร์เป็นวิธีปฏิบัติทั่วไป แต่อันตรายมากผู้โจมตีสามารถเรียกใช้คำสั่งใด ๆ ที่บริการนักเทียบท่าสามารถเรียกใช้ซึ่งโดยทั่วไปจะให้การเข้าถึงระบบโฮสต์ทั้งหมดเมื่อบริการนักเทียบท่าทำงานเป็นรูท "
ฉันรู้ว่ามันช้าไปหน่อย แต่ฉันหวังว่าคำตอบของฉันจะให้ข้อมูลเชิงลึกมากมาย
ผมขอพูดถึง Unix Sockets ก่อน
คำว่า Sockets มักหมายถึง IP Sockets สิ่งเหล่านี้คือสิ่งที่ผูกไว้กับพอร์ต (และที่อยู่) เราส่งคำขอ TCP ไปยังและรับคำตอบจาก
ซ็อกเก็ตอีกประเภทหนึ่งคือซ็อกเก็ต Unix ซ็อกเก็ตเหล่านี้ใช้สำหรับIPC (Interprocess Communication) เรียกอีกอย่างว่า Unix Domain Sockets ( UDS ) Unix Sockets ใช้ระบบไฟล์ภายในสำหรับการสื่อสารในขณะที่ IP Sockets ใช้เครือข่าย
หางภูตสามารถฟังสำหรับหางเครื่องยนต์คำขอ API unix, tcp, and fd
ผ่านสามประเภทที่แตกต่างกันของซ็อกเก็ต:
โดยค่าเริ่มต้นซ็อกเก็ตโดเมน unix (หรือซ็อกเก็ต IPC) ถูกสร้างขึ้นที่ /var/run/docker.sock
ให้เราดูตัวอย่างสด :
Docker Server ใช้ซ็อกเก็ตนี้เพื่อฟัง REST API และไคลเอนต์ใช้ซ็อกเก็ตเพื่อส่งคำขอ API ไปยังเซิร์ฟเวอร์
curlสามารถพูดคุยกับ Unix Socket ผ่าน
--unix-socket
แฟล็ก เนื่องจาก Docker Server API ถูกเปิดเผยเป็น REST เราจึงจำเป็นต้องส่งคำสั่งผ่าน HTTP นอกจากนี้เนื่องจากเซิร์ฟเวอร์นี้อยู่ในระบบ (โปรดจำไว้ว่าระบบไฟล์) เราสามารถส่งผ่านชื่อโฮสต์ใดก็ได้ใน URL (หรือยึดติดกับ localhost ซึ่งจะทำงานได้ดีเช่นกัน!) เซิร์ฟเวอร์ไม่สนใจชื่อโฮสต์เพียงเส้นทาง
curl --unix-socket /var/run/docker.sock http://localhost/images/json | jq
[
{
"Containers": -1,
"Created": 1525888860,
"Id": "sha256:24a77bfbb9ee3aeef9e24766ad6e9fa57f85c67596f154e8916e4f314067e149",
"Labels": null,
"ParentId": "",
"RepoDigests": [
"postgres@sha256:b06cdddba62f1550a1c674270814e72eaa8734d95912019b4ddc288b650ad67d"
],
"RepoTags": null,
"SharedSize": -1,
"Size": 39507096,
"VirtualSize": 39507096
}
]
คำสั่งบางอย่าง :
คุณสามารถทำหลายอย่างด้วย docker.sock
โดยพื้นฐานแล้วมันจะเปิดเผยโฮสต์ Docker daemon ไปยังคอนเทนเนอร์ ดังนั้นคุณสามารถเรียกใช้ docker api / client จากคอนเทนเนอร์ของคุณเพื่อเริ่ม / หยุด / สร้างอิมเมจ / คอนเทนเนอร์เช่นเรียกคำสั่งเหล่านั้นโดยตรงบนโฮสต์