DNS ของ Container และ User-Defined Networks
ทำไม Default Bridge ถึงไม่มี DNS
หัวข้อที่มีชื่อว่า “ทำไม Default Bridge ถึงไม่มี DNS”อย่างที่เห็นในบทเรียนก่อนหน้า container บน default bridge สามารถสื่อสารกันผ่าน IP address ได้ แต่ไม่สามารถ resolve ชื่อกันได้ นั่นเป็นเพราะ default bridge (docker0) เป็น legacy network ที่ Docker สร้างขึ้นก่อนที่จะมี embedded DNS
เมื่อคุณสร้าง user-defined bridge network Docker จะเพิ่ม DNS resolver อัตโนมัติให้ container ทุกตัวบน network นั้นสามารถ resolve ชื่อกันได้ทันที
สร้าง User-Defined Network
หัวข้อที่มีชื่อว่า “สร้าง User-Defined Network”ใช้ docker network create เพื่อสร้าง bridge network ของคุณเอง:
docker network create appnetDocker จะสร้าง bridge network ชื่อ appnet และกำหนด subnet ให้โดยอัตโนมัติ
รัน Container บน Network ที่กำหนดเอง
หัวข้อที่มีชื่อว่า “รัน Container บน Network ที่กำหนดเอง”ใช้ flag --network เพื่อแนบ container เข้ากับ appnet เมื่อรัน:
docker run -d --name web --network appnet nginx:alpinedocker run -d --name client --network appnet alpine sleep 300ทั้งสอง container ตอนนี้อยู่บน appnet และมี DNS resolver ของ Docker ให้บริการ
Ping ด้วยชื่อ Container
หัวข้อที่มีชื่อว่า “Ping ด้วยชื่อ Container”จาก client ลอง ping web ด้วยชื่อ:
docker exec client ping -c 3 webการ ping สำเร็จ! DNS resolver ของ Docker แปลชื่อ web เป็น IP address ของ container นั้นโดยอัตโนมัติ
ตรวจสอบ Network
หัวข้อที่มีชื่อว่า “ตรวจสอบ Network”ดูรายละเอียด network รวมถึง container ที่เชื่อมต่ออยู่:
docker network inspect appnetล้างข้อมูล
หัวข้อที่มีชื่อว่า “ล้างข้อมูล”docker stop web clientdocker rm web clientdocker network rm appnetลงมือปฏิบัติ: DNS บน User-Defined Network
หัวข้อที่มีชื่อว่า “ลงมือปฏิบัติ: DNS บน User-Defined Network”# Create a user-defined bridge network
docker network create appnet
# Start an nginx container on appnet
docker run -d --name web --network appnet nginx:alpine
# Start a client container on appnet and ping web by name
docker run --rm --name client --network appnet alpine ping -c 3 web
# Inspect the network to see attached containers
docker network inspect appnet
# Cleanup
docker stop web && docker rm web
docker network rm appnetข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| ต่อกันด้วย IP address | ไม่ต้องพึ่ง DNS resolver ใด ๆ | ต้องคอย query IP ใหม่ทุกครั้งที่ container restart เพราะ IP เปลี่ยนได้เสมอ |
| ต่อกันด้วยชื่อ container (DNS) | resolve ชื่อเป็น IP ให้อัตโนมัติ อ้างอิงได้แม้ IP จะเปลี่ยน | ใช้ได้เฉพาะบน user-defined network เท่านั้น ไม่ทำงานบน default bridge |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- Hardcode IP address ของ container ไว้ในโค้ดหรือ environment variable แทนที่จะใช้ชื่อ container เป็น DNS name ทำให้ระบบพังทันทีที่ container ถูกสร้างใหม่และได้ IP อื่น
- คาดหวังว่า DNS resolution จะทำงานบน default bridge network ทั้งที่ embedded DNS resolver ของ Docker รองรับเฉพาะ user-defined network เท่านั้น
- ลืมว่า container ต้องอยู่บน user-defined network เดียวกันจริง ๆ ถึงจะ resolve ชื่อกันได้ — อยู่คนละ user-defined network ก็ resolve กันไม่ได้เหมือนกัน
💡 ตัวอย่างจากของจริง
ใน
docker-compose.ymlชื่อ service เองก็คือ DNS hostname อยู่แล้ว เช่น servicewebเชื่อมต่อ database ได้ด้วยdb:5432ตรง ๆ โดยไม่ต้องรู้ IP เลย เพราะ Compose สร้าง user-defined network ให้อัตโนมัติและลงทะเบียน DNS ของทุก service ไว้ในนั้น