วิธีแก้ปัญหา docker ไม่สามารถต่อ Database ได้
เมื่อไม่กี่วันมานี้ผมเจอปัญหาว่าระบบที่รันอยู่บน docker ที่ผมกำลังพัฒนาอยู่ไม่สามารถเชื่อมต่อ database ที่อยู่ในวง 172.17.x.x
ได้ (docker daemon บน Windows) หลังจากลองหาข้อมูลซักพักหนึ่งก็พบว่า จริงๆแล้วมันเป็นปัญหาเส้นผมบังภูเขาจริงๆ แต่ก่อนที่จะแก้ปัญหานี้ได้ เราต้องมาทำความเข้าใจเกี่ยวกับ Docker Network เบื้องต้นกันก่อนดีกว่า
ประเภทของ Docker Network
โดยปกติแล้ว Docker จะสามารถแบ่ง Network ออกได้เป็น 5 ประเภทประกอบด้วย (ไม่รวม custom และพวก 3rd party)
None
คือการรัน container ในระบบปิด ที่ไม่สามารถออก network ภายนอกได้ ปกติเรามักสร้างNone
network ไว้เชื่อมกับ custom network driver ของเราเองBridge
คือการรัน container ที่สามารถเชื่อมต่อไปยัง host network หรือถ้าพูดง่ายๆก็คือ าสามารถออก internet ได้ โดยถ้าเราสั่งรัน container โดยไม่ระบุ network driver ก็จะได้Bridge
มาเป็น default network เสมอ ซึ่งBridge
จะมี Subnet และ Gateway เป็นของตัวเองHost
คือการรัน container บน host network เลย จะไม่มีการแยก network ระหว่าง container และ docker host เหมือนในBridge
Overlay
คือการรัน container ที่มีการคุยกันข้าม docker daemons (host network) ถ้ามีโจทย์แนวๆการทำ distributed network และต้องการให้ container สามารถคุยกันได้ บน host ที่ต่างกันOverlay
ก็จะเป็น network อีกประเภทหนึ่ง ที่เราควรศึกษาเพิ่มดูMacVlan
คือการรัน container ที่สามารถทำให้ container วิ่งไปยัง router ที่ต้องการได้ โดยไม่ต้องผ่าน host network
ปัญหาคืออะไร
ทีนี้กลับมาที่ปัญหาที่ผมเจอ ก็คือใน Environment ที่ผมกำลังพัฒนาอยู่ จำเป็นต้องติดต่อ SQL Server ไปยัง ip 172.17.11.x
(ไม่มี domain) ซึ่งเมื่อลองรันก็พบว่า ไม่สามารถเชื่อมต่อได้ เจอ error ว่า timeout ตลอดเวลา
โดยในการรัน docker ดังกล่าว ผมได้ใช้งาน bridge
network (ไม่ได้เลือกอะไร รันเป็น default ให้อยู่แล้ว) จึงลองทำการ inspect
เพื่อหาสาเหตุว่าทำไมมันถึง timeout ด้วยคำสั่ง
docker network inspect bridge
และพบว่า default Subnet ของ docker ถูกตั้งเอาไว้ที่ 172.17.0.0/16
ซึ่งการระบุ Subnet นี้ส่งผลทำให้ database connection มันวิ่งวนจน timeout นั้นเอง
วิธีแก้ไข
เมื่อเจอแบบนี้ สิ่งที่ต้องทำก็คือ แก้ไข Subnet ให้เป็นค่าอื่นไป โดยในที่นี้เราจะเปลี่ยนให้เป็น 172.17.10.1/24
เพื่อไม่ให้มันชนกัน
ในการแก้ไขก็เพียงไปที่ Setting ของ docker (คลิกขวาที่รูปปลาวาฬ > Setting) เลือก tab Daemon และเปลี่ยนจาก Setting จาก Basic เป็น Advance จากนั้นระบุ bridge ip
เป็น http://172.17.10.1/24
จากนั้นลองเช็คด้วยคำสั่ง docker network inspect bridge
อีกครั้งจะพบว่า subnet เปลี่ยนเป็นที่เรียบร้อยแล้ว
ปัญหานี้ น่าจะไม่ใช่ปัญหาที่เจอกันทุกคน นอกจากว่า Environment ที่คุณกำลังพัฒนาอยู่จำเป็นต้องติดต่อไปยัง IP ที่อยู่ในวง 172.17.10.1/24
และถ้าคุณเจอปัญหานี้ หวังว่าบทความนี้จะช่วยคุณได้นะครับ
reference: Docker Network Overview