Run docker ใน docker ห๊ะ!?

Chokchai Phatharamalai
odds.team
Published in
2 min readMay 2, 2019

เรื่องมันเริ่มจาก ผม run Jekins ใน docker แล้วพอจะให้ Jenkins compile go ผม ก็ไม่อยากลง go ใน Jenkins container เพราะอยากให้แต่ละ container ทำอย่างละเรื่องน่าจะดีกว่า

คิดได้ดังนี้ก็เริ่มหาวิธี run docker ใน docker เริ่มจาก

ลง docker ใน Jenkins ก่อน

https://github.com/juacompe/dockerized-jenkins-with-docker

ลองเช็คดูจะเห็นว่าใน container ของ Jenkins มีคำสั่ง docker ละ

/var/run/docker.sock

จาก implementation ของ Docker การ runคำสั่ง docker ข้างใน docker container จะเจอปัญหา low level technical เยอะมาก ซึ่งสามารถอ่านรายละเอียดเพิ่มเติมได้จากบล็อก ~jpetazzo/Using Docker-in-Docker for your CI or testing environment? Think twice.

วิธีที่ดีกว่าคือการให้ข้างใน container มีแต่คำสั่ง docker แต่ไม่มี docker daemon run อยู่ เราจะใช้ docker daemon จาก host นี่แหละ ซึ่งเราสามารถทำสิ่งนั้นได้โดยการ mount /var/run/docker.sock เข้าไปใน container แค่นี้ เวลาเราสั่ง docker run จากใน container ก็จะเหมือนเราสั่ง docker run จากเครื่อง host เลย

ทำไมต้องใช้ root?

เนื่องจาก user jenkins ไม่มีสิทธิ์ access /var/run/docker.sock ทางออกก็จะมี 1. run ด้วย root หรือไม่ก็ 2. add user jenkins ใส่ group docker และใช้ option--privileged ตอน run ผมเลือกไปท่า 1 เพราะความมักง่าย :P

เท่านี้เราก็สามารถ run docker ข้างใน docker ได้แล้ว

จากรูป จะเห็นว่า docker ps ที่เครื่อง host จะเห็น container ที่เรา run จากใน Jenkins ราวกับว่าเรา run คำสั่ง docker ที่เครื่อง host เลย เป็นเพราะเราใช้ daemon ของเครื่อง host นั่นเอง

มาดูสรุปใน docker-compose file กัน

เท่านี้ใน Jenkins เราก็สามารถสั่งคำสั่ง docker ได้เลย ไม่ต้องไปลงพวก node หรือ go ใน Jenkins ได้แล้ว

คำเตือน: เวลา mount path ต้อง mount จาก path ของเครื่อง host นะ

เนื่องจากจริง ๆ แล้วเราใช้ docker daemon จากเครื่อง host เวลาเราใช้ option -v เพื่อ mount path ใน Jenkins (ที่อยู่ใน docker) เราต้องใช้ path ของเครื่อง host แทนนะ เพราะจริง ๆ ตัว daemon อยู่ที่เครื่อง host

Credits:

--

--