Coding Gun

จัดการกับ Docker Network

Docker network คือการเชื่อม(connected) container เข้าหากันทำให้ container สามารถคุยกันได้ ซึ่ง container ไม่สามารถจะทำงานด้วยตัวคนเดียวได้ ดังนั้นเราจึงต้องสร้าง network ขึ้นมา ซึ่ง network ใน docker จะมีความแตกต่างจาก network แบบ physical และ VM อยู่นิดหน่อย ดังนั้นเราจึงต้องเข้าใจการทำงานของ docker network เพื่อที่เวลาใช้งานเราจะได้เลือกวิธีการเชื่อมต่อ(networking) ไห้ถูกต้องและเหมาะสมกับงาน

Network ประเภทต่างๆ

ในการสร้าง Docker network เราจะต้องเลือกวิธีการเชื่อมต่อของ network หรือ Driver โดยที่ Docker จะ support Driver ต่างๆ ดังนี้

Driver คำอธิบาย
bridge ถ้าเราไม่ได้ระบุ driver Docker จะสร้าง network ด้วย Bridge network
host ทำให้ network ของ Host และ Container เป็น network เดียวกัน อ่านต่อ
none ทำให้ container นี้ run อยู่โดยจะไม่มีการเชื่อมต่อ network ใดๆเลย
overlay เป็นการเชื่อมต่อ network ข้ามเครื่อง ใช้ในการสร้าง Cluster ของ containers อ่านต่อ
ipvlan เป็น network ที่สามารถใช้ได้ทั่ง IPv4 และ IPv6 และจะ share MAC Address
macvlan เป็น network ที่ container แต่ละตัวจะมี MAC Address

ถ้าต้องการ Network ประเภทอื่นๆนอกจากนี้ เราต้องติดต้ัง plugins เข้ามาเพิ่ม ซึ่ง network ที่ list มาในตารางข้างบนนี้เป็นแค่ built-in network ที่มากับ Docker เท่านั้น

Bridge Network

Bridge network คือ การแยก(Isolated) Network ของ Containers ออกจาก Network ของ Host และ Network อื่นๆ Containers แต่ละตัวใน Network นี้จะสามารถสื่อสารกันได้ แต่จะไม่สามารถสื่อสารกับ service อื่นๆที่อยู่นอก Bridge network นี้ได้

ซึ่ง Bridge network จะเป็น Default network ถ้าเราไม่ระบุ driver ตอนสร้าง network หรือ container Docker จะสร้าง network ที่เป็น Bridge ให้

ถ้าใครเคยใช้งาน VM มาก่อน การสร้าง Bridge network ใน container จะเหมือนกับการสร้าง NAT Network ใน VM แต่การทำงานหลังบ้านจะไม่เหมือนกัน

Host Network

ปกติแล้ว network ของเครื่อง Host และ network ของ Container จะแยกกัน แต่ถ้เราต้องการให้ network ของ Host และ Container เป็น network เดียวกันเราจะใช้ parameter แบบนี้

$ docker run --network=host [ชื่อ image]

ซึ่งถ้าเราสร้าง Docker container ขึ้นมาด้วยคำสั่งนี้เราจะได้ container ที่สามารถเข้าถึง network ต่างๆที่เครื่อง host ของเราเชื่อมต่ออยู่

ส่วนใหญ่เราจะใช้ Host network ในกรณีที่เราต้องการใช้เข้าถึง service ต่างๆ ที่ run อยู่บนเครื่อง Host เช่น เรียกใช้ Web application ผ่านทาง localhost

Overlay Network

Overlay network คือ การสร้าง network ที่มีเครื่อง Host มากกว่า 1 เครื่อง เราจะใช้ Overlay network กับ Docker Swarm clusters ซึ่งจะมี Docker daemon รันอยู่

เราจะใช้ Overlay network ในกรณีที่เราต้องการ High Availability ซึ่งต้องมี Docker Host มากกว่า 1 เครื่อง

ความแตกต่างของ Network บน Container และ VM

การทำงานของ Network บน Container จะมีความแตกต่างกันตรงที่ Container จะแบ่ง network โดยใช้ namespaces และ iptables ซึ่งทุกอย่างจะถูกจัดการโดย Operating System(OS)

แต่ VM จะทำการสร้าง Stack ของ Network ขึ้นมาเป็น Virtualization อีก Layer เช่น บน HyperV เราสามารถเข้าไปปรับแต่ง configuration ของ Virtual Switch ได้

Docker command สำหรับจัดการ Network

เราสามารถจัดการกับ docker network ได้ด้วยคำสั่งต่างๆเหล่านี้่

List รายชื่อ Network ท่ีมีอยู่ในเครื่อง

เมื่อเราต้องการ list รายชื่อ Network ที่มีอยู่ในเครื่อง เราจะใช้คำสั่ง

$ docker network ls

โดยที่เริ่มต้น Docker จะสร้าง Network มาให้เรา 3 ตัว

NETWORK ID     NAME                                    DRIVER    SCOPE
b8b6509ebc32   bridge                                  bridge    local
dccf784a75c7   host                                    host      local
d8d8c91929fc   none                                    null      local
  1. bridge เป็น default Bridge network ชื่อ bridge
  2. host เป็น default Host Network ชื่อ host
  3. none ถ้าเรานำ container มาไว้ใน network ชื่อ none จะกลายเป็น container ที่ไม่มี network

สร้าง User-defined Network

เราสามารถสร้าง Network ของเราขึ้นมาเองด้วยคำสั่ง

$ docker network create [ชื่อ network]

ซึ่งเราสามารถระบุ ประเภทของ network(driver) ได้ด้วยคำสั่ง

$ docker network create -d bridge [ชื่อ network]

ในตัวอย่างนี้เราจะสร้าง docker network แบบ bridge ขึ้นมา โดยระบ parameter -d bridge เข้าไปในคำสั่ง docker network create

ซึ่ง driver หรือประเภทของ network เราสามารถเลือกได้จากตารางด้านบน

นำ Container เข้ามาใน Network

เราสามารถกำหนด Network ได้ตั้งแต่ตอนสร้าง Container ด้วย –net เหมือนในหัวข้อที่แล้ว แต่ถ้่าเราอยากจะเปลี่ยน Network ใหม่โดยที่ไม่ต้องการสร้าง Container ขึ้นมาใหม่ล่ะ จะทำยังไง? คำตอบคือ

  1. Stop container นัั้นก่อน
    $ docker container stop [ชื่อ container]
    
  2. นำ Container เข้าไปใน Network ด้วนคำสั่ง
    $ docker network connect [ชื่อ Network] [ชื่อ Container]
    
    การใช้ docker network connect จะเป็นการเพิ่ม network interface card เข้าไปในเครื่อง เช่นในตัวอย่างนี้เมื่อ container สร้างขึ้นมาแล้วจะมี interface eth0 อยู่แล้ว หลังจาก connect จะเป็นการเพิ่ม interface eth1 เข้ามา นั่นหมายความว่า container จะ connect อยู่กับ network เดิมที่สร้าง และ network ใหม่ที่เพิ่มเข้ามาทั้งคู่
  3. Start container กลับชึ้นมาทำงานด้วยคพสั่ง
    $ docker container start [ชื่อ container]
    

Network Inspect

เราสามารถดูรายละเอียดของ Network ได้ด้วยคำสั่ง

$ docker network inspect [ชื่อ Network]

โดยที่ผลลัพธ์จะออกมาเป็น

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[
    {
        "Name": "bridge",
        "Id": "c961a1fec3f6686c6707b8da645a69e5993877978068a3ec0e32afe575a8d6da",
        "Created": "2024-03-20T21:49:08.457359458Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

ซึ่งข้อมูลที่เราได้จาก docker network inspect จะมีดังนี้

  1. ชื่อของ Network ในบรรทัดที่ 3
  2. ประเภทของ Network หรือ Driver ในบรรทัดที่ 7
  3. Subnet ของ Network นี้ ในบรรทัดที่ 14
  4. Gateway ของ Network นี้ในบรรทัดที่ 15 จะเป็น IP ใน subnet ตัวที่ 2 เช่นในตัวอย่างนี้มี Subnet เป็น 172.17.0.0/16 ดังนั้น Gateway จะเป็น 172.17.0.1
  5. ถ้าอยากรู้ว่าใน Network นี้มี Container ตัวไหนอยู่บ้างในให้ดูที่บรรทัดที่ 26 นี้
Phanupong Permpimol
Follow me

Software Engineer ที่เชื่อในเรื่องของ Process เพราะเมื่อ Process ดี Product ก็จะดีตาม ปัจจุบันเป็นอาจารย์และที่ปรึกษาด้านการออกแบบและพัฒนา Software และ Web Security