Docker network

Docker networks: create a network, connect containers to it and let them talk to each other.

episode
ตอนที่ 10 จาก 17
read
อ่าน 3 นาที

Problems

จากข้อก่อนหน้า เราเอา Nextjs เรียกผ่าน host.docker.internal ซึ่งมันต้องเรียก data ย้อนออกมาที่เครื่อง host ก่อนแล้วย้อนกลับเข้าไปที่ backend

ถ้าเราใช้ network เราจะทำให้ nextjs สามารถเรียกไปที่ backend ได้ตรงๆเลย

Knowing Docker Network

มาทำความรู้จักกับ network command กันก่อน

docker network ls
❯ docker network ls
NETWORK ID NAME DRIVER SCOPE
62490c6249ac bridge bridge local
f995a98564a2 host host local
13fa6f2ef770 none null local

จะเห็นว่ามี network อยู่ 3 ตัว networks เหล่านี้จะเป็นเหมือนวงแลนวงนึง ใครเชื่อมต่อเข้ามาที่วงแล้วนี้ก็จะมองเห็นกันเหมือนที่เครื่องคอมอยู่ในวงแลนเดียวกัน

  1. null -> container ไหนเชื่อมมาที่ none จะไม่ถูกเข้าถึงจากภายนอกได้เลย
  2. host -> ก็คือเครื่องเรานี่แหละ network เส้นนี้จะเชื่อมต่อกับ host นี่แหละ ในหนึ่งเครื่องจะมี host ได้แค่อันเดียว
  3. bride เป็นวงแลนเส้นนึง

Create Network

เราสามารถสร้าง network ได้ด้วย ซึ่งจะมี driver เป็น bridge ได้เท่านั้นนะ

จากตัวอย่างของเราก่อนหน้า เราก็จะเอา Next มาต่อเข้าที่ network ที่ชื่อว่า my_bridge1 แล้วก็เอา Backend มาต่อเข้าที่ network ที่ชื่อว่า my_bridge1 เช่นกัน

เราจะสร้าง network ใน docker ด้วยคำสั่ง

docker network create my_bridge1
❯ docker network ls
NETWORK ID NAME DRIVER SCOPE
62490c6249ac bridge bridge local
f995a98564a2 host host local
22fb86b854db my_bridge1 bridge local
13fa6f2ef770 none null local

Connect container to network

connect when run container

docker run --name next -p 3000:3000 --network my_bridge1 -d next

ตรวจสอบว่า network มี container อะไร connect อยู่บ้างด้วยคำสั่ง

docker inspect <network name>
❯ docker inspect my_bridge1
[
{
"Name": "my_bridge1",
"Id": "22fb86b854db4e238e58c34f5a2f172840f8cdc0d35fe2e0c7aa5868dd4f1004",
"Created": "2024-07-01T20:18:10.448458201+07:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.228.0/24",
"Gateway": "192.168.228.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"39324b32c57efd54ebc1f779ec804ab5e3940550f729d3bf1dda3c43a6c2ed0d": {
"Name": "next",
"EndpointID": "e1111b7573e1dce638ff18bb3ccb4374cae2b5d754a30bcd13d0521c6383f896",
"MacAddress": "02:42:c0:a8:e4:02",
"IPv4Address": "192.168.228.2/24",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]

จะเห็นว่ามี next อยู่ในนั้นแล้ว

เหลือ Backend อีกตัวนึง

รอบนี้เราจะ start backend ก่อน แล้วเราจะ connect container เข้าไปที่ network ภายหลัง

docker run --name hono -p 3333:3333 -v ./uploads:/app/uploads -d hono

connect backend to network

docker network connect <network name> <container name>
docker network connect my_bridge1 hono

แล้ว inspect network ดูอีกครั้งหนึง

❯ docker inspect my_bridge1
[
{
"Name": "my_bridge1",
"Id": "22fb86b854db4e238e58c34f5a2f172840f8cdc0d35fe2e0c7aa5868dd4f1004",
"Created": "2024-07-01T20:18:10.448458201+07:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.228.0/24",
"Gateway": "192.168.228.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"39324b32c57efd54ebc1f779ec804ab5e3940550f729d3bf1dda3c43a6c2ed0d": {
"Name": "next",
"EndpointID": "e1111b7573e1dce638ff18bb3ccb4374cae2b5d754a30bcd13d0521c6383f896",
"MacAddress": "02:42:c0:a8:e4:02",
"IPv4Address": "192.168.228.2/24",
"IPv6Address": ""
},
"5fd7e837549bee5ba7d1f581c897bcd06f9ff3791ed030bd06c05bf5f1d2f1c9": {
"Name": "hono",
"EndpointID": "940da611fb052999b73cdef031c2ab8c7f083b7ad7e314a4e65774e0c55189d3",
"MacAddress": "02:42:c0:a8:e4:03",
"IPv4Address": "192.168.228.3/24",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]

เหลือแค่มาแก้ next app ของเราให้เรียกไปที่ backend ผ่าน network

ให้ใส่ชื่อของ container ลงไปตรงๆเลย ถ้าอยู่ใน network เดียวกัน docker จะพาไปที่ container นั้นได้ถูกต้องเองเลย

fetch("http://hono:3333/users").then(
(res) => res.json() as Promise<{ users: { name: string; age: number }[] }>,
);

ก็ให้ build image ใหม่อีกรอบนึง แล้ว run ต่อไปเลยนะ

docker build -t next .
docker run --name next -p 3000:3000 --network my_bridge1 -d next

ลองเปิด browser ดูจะต้องไม่ error นะ

http://localhost:3000/

สุดท้ายก็จะได้ภาพแบบนี้