Docker Networking Bridge Host Overlay

หนึ่งในสิ่งที่ผู้ใช้ Docker มักสับสนคือเรื่อง Networking เมื่อรัน Container หลายตัว ทำไมบางตัวคุยกันได้ บางตัวไม่ได้ ทำไม Container เข้าถึง Internet ไม่ได้ หรือทำไม Port ที่ map ไว้ใช้งานได้จาก Host แต่ Container อื่นเข้าไม่ถึง บทความนี้จะอธิบาย Docker Network Driver ทุกประเภทพร้อมวิธีเลือกใช้ให้ถูกกับแต่ละ Scenario

Docker Networking คืออะไร

Docker มีระบบ Network เป็นของตัวเอง แยกออกจาก Network ของ Host อย่างชัดเจน แต่ละ Container สามารถเชื่อมต่อกับ Network ได้หลาย Network พร้อมกัน Docker จัดการผ่าน Network Driver ซึ่งกำหนดพฤติกรรมการสื่อสาร

หลักการ: Container ที่อยู่ใน Network เดียวกันคุยกันได้โดยตรงผ่านชื่อ Container (DNS อัตโนมัติ) ส่วน Container ต่าง Network ต้องผ่าน Port Mapping หรือเชื่อม Network เพิ่ม

ประเภท Docker Network Driver

DEFAULT

Bridge

Network เสมือนส่วนตัวบน Host เดียว Container ในกลุ่มเดียวกันคุยกันได้ ใช้บ่อยที่สุด

PERFORMANCE

Host

Container ใช้ Network Stack ของ Host โดยตรง ไม่มี NAT ความเร็วสูงสุด แต่ไม่มี Isolation

MULTI-HOST

Overlay

เชื่อม Container ข้าม Host หลายเครื่องได้ ใช้กับ Docker Swarm หรือ Kubernetes

ADVANCED

Macvlan

Container ได้รับ IP จริงในวง LAN ดูเหมือนเป็นเครื่องฟิสิคัล เหมาะกับ Network Legacy

Bridge Network — ค่าเริ่มต้น

เมื่อรัน Container โดยไม่ระบุ Network Docker จะใช้ Bridge Network ชื่อ bridge อัตโนมัติ แต่ Bridge เริ่มต้นนี้ไม่รองรับ DNS Resolution ระหว่าง Container ต้องสร้าง User-defined Bridge แทน

# สร้าง Bridge Network ใหม่ (แนะนำ) docker network create my-app-net # รัน Container ใน Network เดียวกัน docker run -d --name db --network my-app-net mysql:8 docker run -d --name app --network my-app-net myapp:latest # app สามารถเชื่อมต่อ db ผ่านชื่อ "db" ได้ทันที # เช่น DB_HOST=db ใน environment variable

ข้อดีของ User-defined Bridge

# สร้าง Network พร้อมกำหนด Subnet docker network create \ --driver bridge \ --subnet 172.20.0.0/16 \ --gateway 172.20.0.1 \ production-net # ดู Network ทั้งหมด docker network ls # ดูรายละเอียด Network docker network inspect my-app-net

Host Network — ความเร็วสูงสุด

Container ใช้ Network Interface ของ Host โดยตรง ไม่มี Virtual Network Layer ทำให้ Latency ต่ำและ Throughput สูง เหมาะกับ Application ที่ต้องการ Network Performance สูง เช่น Monitoring Agent หรือ High-frequency Trading

# รัน Container แบบ Host Network docker run -d --network host nginx # Nginx จะ Listen Port 80 บน Host โดยตรง # ไม่ต้องทำ -p 80:80 แล้ว

ข้อควรระวัง: Host Network ใช้ได้บน Linux เท่านั้น บน Mac/Windows (Docker Desktop) ใช้งานได้แต่ประสิทธิภาพไม่ต่างจาก Bridge เพราะยังมี VM Layer อยู่

Overlay Network — ข้าม Host หลายเครื่อง

ใช้ใน Docker Swarm หรือ Kubernetes เพื่อให้ Container ที่รันบน Node ต่างเครื่องสื่อสารกันได้เหมือนอยู่ใน Network เดียวกัน ข้อมูลจะถูก Encapsulate ด้วย VXLAN Protocol

# ต้องเปิด Swarm Mode ก่อน docker swarm init # สร้าง Overlay Network docker network create \ --driver overlay \ --attachable \ swarm-net # Deploy Service ใน Overlay Network docker service create \ --name webapp \ --network swarm-net \ --replicas 3 \ nginx

None Network — ปิด Network ทั้งหมด

Container ไม่มี Network Interface เลย (ยกเว้น Loopback) เหมาะสำหรับ Batch Job ที่ไม่ต้องการ Network เลย หรืองานที่ต้องการ Isolation สูงสุด

# รัน Container ไม่มี Network docker run --network none alpine sh

เปรียบเทียบ Docker Network Driver

DriverUse CaseDNSข้าม HostPerformance
bridgeDefault, Local Dev, Single Host✅ (User-defined)❌ดี
hostHigh Performance, MonitoringHost DNS❌ดีที่สุด
overlaySwarm, Multi-host✅✅ดี (VXLAN overhead)
macvlanLegacy Network, Physical IP❌❌ดีมาก
noneBatch Job, Max Isolation❌❌N/A

Docker Compose กับ Network

Docker Compose สร้าง Bridge Network ให้อัตโนมัติ Services ทุกตัวใน Compose File เดียวกันอยู่ใน Network เดียวกันโดย Default

# docker-compose.yml services: web: image: nginx ports: - "80:80" networks: - frontend - backend db: image: mysql:8 networks: - backend # db อยู่แค่ backend — web เข้าถึงได้ แต่ภายนอกเข้าไม่ได้ networks: frontend: backend: internal: true # internal: true — ตัด Internet ออก ปลอดภัยขึ้น

คำสั่งจัดการ Network ที่ใช้บ่อย

# ดู Network ทั้งหมด docker network ls # ดูรายละเอียด + Container ที่อยู่ใน Network docker network inspect <network-name> # เชื่อม Container เข้า Network เพิ่ม (Runtime) docker network connect my-net my-container # ถอด Container ออกจาก Network docker network disconnect my-net my-container # ลบ Network ที่ไม่มี Container ใช้ docker network prune

แก้ปัญหา Container คุยกันไม่ได้

ปัญหาที่พบบ่อยเมื่อ Container ติดต่อกันไม่ได้:

# ทดสอบ Connectivity จาก Container หนึ่งไปอีกตัว docker exec -it app ping db docker exec -it app curl http://db:8080/health

ทำความเข้าใจ IP Address ใน Docker Network

เมื่อสร้าง Container บน Docker แต่ละ Container จะได้รับ IP Address ส่วนตัวภายใน Network ที่มันเชื่อมอยู่ การทำความเข้าใจโครงสร้าง IP นี้ช่วยให้แก้ปัญหา Network ได้เร็วขึ้นมาก:

# ดู IP ของ Container ทุกตัวใน Network docker network inspect my-app-net --format '{{range .Containers}}{{.Name}}: {{.IPv4Address}}{{"\n"}}{{end}}' # กำหนด Static IP ให้ Container (ต้องมี Subnet ที่กำหนดเอง) docker run -d \ --name db \ --network my-app-net \ --ip 172.20.0.10 \ mysql:8 # ดู Gateway ของ Network docker network inspect my-app-net | grep Gateway

การกำหนด Static IP ช่วยให้ Config บางอย่างที่ต้องการ IP แน่นอน เช่น Firewall Rule หรือ External Service ที่ต้อง Whitelist IP ทำงานได้ถูกต้องแม้ Container ถูก restart

วิธีวางแผน Network Architecture สำหรับ Application บน VPS

ก่อนที่จะ Deploy Application จริงบน VPS ควรวางแผน Network Architecture ให้ดีตั้งแต่ต้น เพราะการแก้ Network ทีหลังเมื่อ Application รันอยู่แล้วจะยุ่งยากมากกว่า หลักการออกแบบที่ดี:

ตัวอย่าง Network Architecture แบบ Three-Tier สำหรับ Web Application ขนาดกลาง:

# สร้าง Network แยก 3 ชั้น docker network create --driver bridge --subnet 172.21.0.0/24 app-frontend docker network create --driver bridge --subnet 172.22.0.0/24 --internal app-backend docker network create --driver bridge --subnet 172.23.0.0/24 --internal app-database # Nginx (Frontend) — ต้องการ Internet + ต้องคุย Backend docker run -d --name nginx \ --network app-frontend \ -p 80:80 -p 443:443 \ nginx # เชื่อม nginx เข้า backend ด้วย docker network connect app-backend nginx # App Server — คุยได้เฉพาะ Backend + Database docker run -d --name app \ --network app-backend \ myapp:latest docker network connect app-database app # MySQL — อยู่ใน Database Network เท่านั้น docker run -d --name mysql \ --network app-database \ -e MYSQL_ROOT_PASSWORD=secret \ mysql:8

ด้วย Architecture นี้ ถ้า Nginx ถูก Hack ผู้โจมตีจะสามารถเข้าถึงได้เฉพาะ Backend Network ไม่สามารถเข้าถึง MySQL โดยตรงได้ เพราะ MySQL อยู่คนละ Network กับ Nginx การออกแบบแบบ Defense-in-Depth ลักษณะนี้ทำให้แม้ Service ชั้นนอกถูก Compromise ข้อมูลสำคัญในฐานข้อมูลยังได้รับการปกป้องจากชั้น Network ภายใน ซึ่งเป็น Best Practice ที่ทีม Security แนะนำสำหรับทุก Application ที่ Deploy บน Production VPS

ความปลอดภัยของ Docker Network บน VPS

การตั้งค่า Network ให้ถูกต้องเป็นส่วนสำคัญของการ Hardening ระบบบน VPS ข้อแนะนำด้านความปลอดภัยที่ควรปฏิบัติ:

# จำกัด MySQL ให้ Bind แค่ localhost docker run -d \ -p 127.0.0.1:3306:3306 \ --name db \ --network backend-net \ -e MYSQL_ROOT_PASSWORD=secret \ mysql:8 # ตรวจสอบ Port ที่เปิดอยู่บน Host ss -tlnp | grep LISTEN # ดู iptables rule ที่ Docker สร้าง sudo iptables -L DOCKER -n --line-numbers

Macvlan Network — กรณีใช้งาน Legacy System

Macvlan เหมาะสำหรับสถานการณ์ที่ Container ต้องได้รับ IP จริงในวง LAN เช่น ต้องการให้ Container ดูเหมือนเป็นเครื่องใหม่อีกเครื่องบน Network เดียวกัน สถานการณ์ที่นิยมใช้:

# สร้าง Macvlan Network (ต้องรู้ Interface ของ Host ก่อน) ip link show # หา Interface เช่น eth0 หรือ ens3 docker network create \ --driver macvlan \ --subnet=192.168.1.0/24 \ --gateway=192.168.1.1 \ -o parent=eth0 \ macvlan-net # รัน Container ที่มี IP จริงในวง LAN docker run -d \ --name legacy-app \ --network macvlan-net \ --ip 192.168.1.100 \ nginx

ข้อควรระวัง Macvlan: Host และ Container ใน Macvlan Network เดียวกันสื่อสารกันโดยตรงไม่ได้ (เป็นข้อจำกัดของ Linux Kernel) ต้องสร้าง Macvlan Interface เพิ่มบน Host เองหากต้องการ

Docker Network กับ Docker Swarm — ขยายระบบข้าม Node

เมื่อธุรกิจเติบโตและ VPS เครื่องเดียวไม่เพียงพอ Docker Swarm ช่วยให้ขยาย Container ไปรันบน Node หลายเครื่องได้ โดย Overlay Network จะเชื่อม Container ทุกตัวเข้าด้วยกันอย่างโปร่งใส:

# เพิ่ม Node เข้า Swarm (รันบน Worker Node) docker swarm join --token <TOKEN> <MANAGER-IP>:2377 # ดูสถานะ Node ทั้งหมด (รันบน Manager) docker node ls # Scale Service ขึ้น docker service scale webapp=5 # ดูสถานะ Service docker service ps webapp
Scenario Network Driver เหตุผล
Web App + DB บน VPS เดียว User-defined Bridge DNS อัตโนมัติ, Isolation ดี
Monitoring Agent Host ต้องเข้าถึง Host Network Stats โดยตรง
Microservices หลาย VPS Overlay เชื่อม Container ข้าม Node ได้ทันที
ระบบ Legacy ต้องการ IP จริง Macvlan Container ได้ IP ใน LAN จริง

VPS สำหรับรัน Docker มีที่ AsiaGB

VPS AsiaGB รองรับ Docker และ Docker Compose เต็มรูปแบบ Root Access ตั้งค่า Network ได้อิสระ เริ่มต้น 500 บาท/เดือน

ดูแพ็กเกจ VPS