Custom Networks และการแยก Container
ทำไมต้องแยก Network
หัวข้อที่มีชื่อว่า “ทำไมต้องแยก Network”การใส่ container ทั้งหมดไว้บน network เดียวกันหมายความว่าพวกเขาสามารถสื่อสารกันได้ทั้งหมด — ไม่ว่าจะเป็น frontend กับ database หรือ microservice กับ microservice อื่นที่ไม่ควรรู้จักกัน การแยก network เป็นมาตรการความปลอดภัยที่ไม่มีต้นทุน (zero-cost): container บน network ต่างกันเข้าถึงกันไม่ได้ เว้นแต่จะเชื่อมต่อเข้ากับทั้งสอง network อย่างชัดเจน
การสร้าง network แยกสำหรับแต่ละ tier ของ application ช่วยให้คุณ:
- จำกัดการสื่อสารเฉพาะที่จำเป็น
- ลดพื้นที่การโจมตีหากมี container ถูก compromise
- สร้างสถาปัตยกรรมที่ชัดเจนและ document ตัวเองได้
สร้าง Network ที่แยกกัน
หัวข้อที่มีชื่อว่า “สร้าง Network ที่แยกกัน”docker network create ใช้ driver bridge เป็นค่าเริ่มต้น จึงละ --driver bridge ได้เพื่อความกระชับ สร้าง network สองตัวสำหรับ frontend และ backend:
docker network create frontend-netdocker network create backend-netรัน Container บน Network ที่ต่างกัน
หัวข้อที่มีชื่อว่า “รัน Container บน Network ที่ต่างกัน”docker run -d --name frontend --network frontend-net nginx:alpinedocker run -d --name database --network backend-net -e POSTGRES_PASSWORD=example postgres:alpinefrontend และ database อยู่คนละ network จึงสื่อสารกันไม่ได้โดยค่าเริ่มต้น
application แบบ three-tier ทั่วไปจะขยายแนวคิดนี้ไปเป็นสาม network:
| Network | Container ที่แนบอยู่ | เข้าถึงได้ |
|---|---|---|
frontend-net | nginx-proxy, web-app | กันเองเท่านั้น |
backend-net | web-app, api-server | กันเองเท่านั้น |
data-net | api-server, postgres | กันเองเท่านั้น |
web-app เชื่อมต่อทั้ง frontend-net และ backend-net จึงเป็นสะพานเชื่อมสองชั้น ส่วน postgres อยู่บน data-net เพียงอย่างเดียว — nginx proxy เข้าถึง database โดยตรงไม่ได้ แม้จะถูก compromise ก็ตาม
ตรวจสอบว่า Container ไม่สามารถสื่อสารกันได้
หัวข้อที่มีชื่อว่า “ตรวจสอบว่า Container ไม่สามารถสื่อสารกันได้”docker exec frontend ping -c 2 database || echo "Cannot reach database"การ ping ล้มเหลวตามที่คาดหวัง เพราะ frontend อยู่บน frontend-net และ database อยู่บน backend-net
เชื่อมต่อ Container กับ Network เพิ่มเติม
หัวข้อที่มีชื่อว่า “เชื่อมต่อ Container กับ Network เพิ่มเติม”Container ที่กำลังรันอยู่สามารถแนบเข้ากับอีก network หนึ่งได้โดยไม่ต้องรีสตาร์ท:
docker network connect backend-net frontendตอนนี้ frontend มี interface อยู่บนทั้ง frontend-net และ backend-net และสามารถ resolve และเข้าถึง database ด้วยชื่อได้:
docker exec frontend ping -c 2 databaseตัดการเชื่อมต่อและลบ Network
หัวข้อที่มีชื่อว่า “ตัดการเชื่อมต่อและลบ Network”# Detach frontend from backend-net againdocker network disconnect backend-net frontend
# Filter docker network ls to just bridge networksdocker network ls --filter driver=bridge
# Inspect a network's driver, subnet, gateway, and attached containersdocker network inspect frontend-netไม่สามารถลบ network ได้ขณะที่ยังมี container แนบอยู่ — หยุดและลบ container ก่อน แล้วจึงลบ network:
docker network rm frontend-netล้างข้อมูล
หัวข้อที่มีชื่อว่า “ล้างข้อมูล”docker stop frontend databasedocker rm frontend databasedocker network rm frontend-net backend-netลงมือปฏิบัติ: Custom Networks
หัวข้อที่มีชื่อว่า “ลงมือปฏิบัติ: Custom Networks”# Create two isolated networks
docker network create frontend-net
docker network create backend-net
# Run containers on separate networks
docker run -d --name frontend --network frontend-net nginx:alpine
docker run -d --name database --network backend-net -e POSTGRES_PASSWORD=example postgres:alpine
# frontend cannot reach database (different networks)
docker exec frontend ping -c 2 database || echo "Cannot reach database"
# Connect frontend to backend-net so it can reach the database
docker network connect backend-net frontend
# Now frontend can reach database
docker exec frontend ping -c 2 database
# Inspect a network
docker network inspect frontend-net
# Disconnect
docker network disconnect backend-net frontend
# Cleanup
docker stop frontend database && docker rm frontend database
docker network rm frontend-net backend-netข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| รวม container ทั้งหมดไว้บน network เดียว | ตั้งค่าเร็ว ไม่ต้องคิดเรื่อง network topology | container ทุกตัวมองเห็นและเข้าถึงกันได้หมด เพิ่มพื้นที่การโจมตีโดยไม่จำเป็น |
| แยก network ตาม tier (frontend/backend/data) | จำกัดการสื่อสารเฉพาะที่จำเป็น ลดผลกระทบหากมี container ถูก compromise | ต้องบริหารจัดการหลาย network และ connect/disconnect container เอง |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ใส่ container ที่ไม่เกี่ยวข้องกันทั้งหมดไว้บน network เดียว (หรือปล่อยไว้บน default bridge) ทำให้ database ถูกเข้าถึงได้จาก container ไหนก็ได้ที่รันอยู่บนเครื่องเดียวกัน
- ลืมว่า
docker network connectเชื่อม container เข้ากับ network เพิ่มได้ แต่ต้องdocker network disconnectออกเองด้วยเหมือนกัน ไม่ได้หลุดออกเองเมื่อ container หยุดทำงาน - ใช้ network เดียวกันสำหรับทุก environment (dev/staging/prod) ทำให้ container จากคนละ environment ปนกันโดยไม่ได้ตั้งใจ
💡 ตัวอย่างจากของจริง
Docker Compose สร้าง user-defined network แยกให้แต่ละโปรเจกต์โดยอัตโนมัติ (ตั้งชื่อตาม project directory เช่น
myapp_default) เพื่อให้ service ในโปรเจกต์หนึ่งไม่ชนหรือมองเห็น container ของอีกโปรเจกต์บนเครื่อง dev เดียวกัน — เป็น pattern มาตรฐานสำหรับ multi-project local development