network Bridge เริ่มต้น
Default Bridge ทำงานอย่างไร
หัวข้อที่มีชื่อว่า “Default Bridge ทำงานอย่างไร”เมื่อ Docker daemon เริ่มต้น จะสร้าง virtual Ethernet switch ชื่อ docker0 บน host นี่คือ default bridge network ทุก container ที่คุณเริ่มต้นโดยไม่ระบุ --network จะถูกเชื่อมต่อกับ docker0 โดยอัตโนมัติ
Container บน default bridge จะได้รับ IP address จาก subnet 172.17.0.0/16 โดย gateway — และ host เอง — อยู่ที่ 172.17.0.1
flowchart TB host["Host"] bridge["docker0 (172.17.0.1)"] c1["container c1 (172.17.0.2)"] c2["container c2 (172.17.0.3)"] host --> bridge bridge --> c1 bridge --> c2
รัน Container สองตัวและตรวจสอบ IP
หัวข้อที่มีชื่อว่า “รัน Container สองตัวและตรวจสอบ IP”เริ่มต้น nginx container ชื่อ c1 และ Alpine container ชื่อ c2:
docker run -d --name c1 nginx:alpinedocker run -d --name c2 alpine sleep 300ตรวจสอบ IP address ที่ถูกกำหนดให้แต่ละ container:
docker inspect c1 --format '{{.NetworkSettings.IPAddress}}'docker inspect c2 --format '{{.NetworkSettings.IPAddress}}'คุณจะเห็น address เช่น 172.17.0.2 และ 172.17.0.3
Container สามารถ Ping กันผ่าน IP ได้
หัวข้อที่มีชื่อว่า “Container สามารถ Ping กันผ่าน IP ได้”เนื่องจากทั้งสอง container อยู่บน bridge docker0 เดียวกัน การ routing layer-3 ระหว่างพวกเขาจึงทำงานได้ จาก c2 ให้ ping c1 ด้วย IP address:
docker exec c2 ping -c 3 172.17.0.2การ ping สำเร็จ traffic ไหลผ่าน docker0 บน host
การ Resolve ชื่อ Container ไม่ทำงานบน Default Bridge
หัวข้อที่มีชื่อว่า “การ Resolve ชื่อ Container ไม่ทำงานบน Default Bridge”ลองทำ ping เดิมโดยใช้ชื่อ container แทน IP:
docker exec c2 ping c1คำสั่งนี้จะล้มเหลวด้วยข้อความ bad address 'c1' หรือ DNS error ที่คล้ายกัน Default bridge network ไม่มี embedded DNS resolver ดังนั้นจึงไม่สามารถ resolve ชื่อ container ได้ เฉพาะ user-defined network (ครอบคลุมในบทเรียนถัดไป) เท่านั้นที่ให้ DNS อัตโนมัติ
ล้างข้อมูล
หัวข้อที่มีชื่อว่า “ล้างข้อมูล”หยุดและลบทั้งสอง container เมื่อเสร็จสิ้น:
docker stop c1 c2docker rm c1 c2ลงมือปฏิบัติ: ตรวจสอบ IP บน Bridge
หัวข้อที่มีชื่อว่า “ลงมือปฏิบัติ: ตรวจสอบ IP บน Bridge”# Start two containers on the default bridge
docker run -d --name c1 alpine sleep 300
docker run -d --name c2 alpine sleep 300
# Find their IPs
C1_IP=$(docker inspect c1 --format '{{.NetworkSettings.IPAddress}}')
C2_IP=$(docker inspect c2 --format '{{.NetworkSettings.IPAddress}}')
echo "c1 IP: $C1_IP"
echo "c2 IP: $C2_IP"
# Ping c2 from c1 by IP (succeeds)
docker exec c1 ping -c 3 $C2_IP
# Try to ping by name (fails — no DNS on default bridge)
docker exec c1 ping -c 1 c2 || echo "Name resolution failed as expected"
# Cleanup
docker stop c1 c2 && docker rm c1 c2ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
Default bridge (docker0) | ใช้งานได้ทันทีโดยไม่ต้องตั้งค่าอะไรเพิ่ม | ไม่มี DNS resolver ในตัว ต้องต่อกันด้วย IP address ล้วน ๆ |
| User-defined bridge network | มี embedded DNS resolver ให้ resolve ชื่อ container ได้ทันที | ต้องรัน docker network create เพิ่มอีกขั้นก่อนใช้งาน |
| Host network mode | performance สูงสุด ไม่มี NAT overhead ระหว่าง container กับ host | ไม่มี network isolation จาก host เลย container ใช้ network stack เดียวกับ host ตรง ๆ |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- Hardcode IP address ที่ได้จาก
docker inspectไว้ใน config เพราะคิดว่า IP จะคงที่ ทั้งที่ IP เปลี่ยนได้ทันทีเมื่อ container ถูก restart หรือสร้างใหม่ - ใช้งาน default bridge ต่อไปแล้วพยายาม ping container ด้วยชื่อ โดยไม่รู้ว่า default bridge ไม่มี DNS resolver ให้ใช้
- โยน container จากหลายโปรเจกต์ไว้บน default bridge เดียวกันโดยไม่แยก ทำให้ container ทุกตัวมองเห็นและเข้าถึงกันได้หมดโดยไม่ตั้งใจ
💡 ตัวอย่างจากของจริง
GitLab CI และ Jenkins ที่รัน Docker executor จะสร้าง bridge network แยกให้แต่ละ job แทนที่จะใช้ default bridge เพื่อให้ container หลักและ service container (เช่น database สำหรับเทส) resolve ชื่อกันได้ผ่าน DNS โดยไม่ชนกับ job อื่นที่รันขนานกันบน runner เดียวกัน