Containers

Hiểu Đúng Để Làm Chủ Docker Container Networking

Trong Docker, bạn đã bao giờ tự hỏi làm thế nào một web server container có thể “nói chuyện” với một database container?

Hay vì sao một số containers communicate được với nhau, trong khi những containers khác lại không thể nói chuyện được với nhau?

Và điều thú vị nhất là:
Tại sao có các containers ping được với nhau, có một số containers khác lại không thể ping được với nhau ?

Và đặc biệt là: Từ host, bạn luôn có thể ping được đến TẤT CẢ các containers — nhưng từ container thì lại không thể ping được đến 1 container khác.

Nếu bạn đã từng “cảm thấy khó hiểu hay mơ hồ” với networking trong Docker, thì bài viết này sẽ là liều dopamine dẫn bạn đến tận “động cơ networking” bên trong Docker – đơn giản, rõ ràng, và thực chiến.


Contents

Lời mở đầu – Một cách nhìn thực tế về Docker Networking

Chào mừng bạn trở lại với series Docker – DevOps theo phong cách thực chiến.
Tôi là Phương – và hôm nay, chúng ta sẽ giải mã một trong những chủ đề quan trọng nhất khi triển khai microservices đó là:

Docker Container Networking — là nơi mà các containers dùng để kết nối, giao tiếp, tách biệt, và tạo thành nền tảng của mọi ứng dụng phân tán.

Và giống như Solomon Hykes từng nói:

“Containers are about simplicity. Networking should be the same.”

Bài viết này sẽ giúp bạn hiểu đúng – ngay từ nền tảng cơ bản và thực tế nhất.


PHẦN 1 – Default Bridge: Mạng Mặc Định do Docker Tạo Ra Cho Bạn

1️⃣ Docker có những networks nào khi bạn đã cài đặt xong dịch vụ này?

Hãy bắt đầu bằng việc kiểm tra networks mặc định với lệnh:

docker network ls

Docker sẽ hiển thị một danh sách các networks mặc định như sau:

  • bridge  container được tạo ra sẽ trong network này nếu bạn không cấu hình 1 NW khác cho nó

  • host

  • none

Trong đó bridge là quan trọng nhất. Mọi container mặc định đều được đặt vào bridge network này, có nghĩa là Docker sẽ sử dụng network này cho các containers nếu bạn không chỉ định container của bạn sử dụng một network khác.


2️⃣ Chạy thử container web1 trong default bridge

Bây giờ chúng ta khởi chạy một container Apache để quan sát cách Docker hoạt động như thế nào với các lệnh lần lượt như sau:

docker run -d --name web1 httpd:2.4
docker inspect web1

Khi inspect web1 container, bạn sẽ thấy:

  • Docker gán cho web1 một IP

  • IP này thuộc mạng docker0

  • Network này thường có dải địa chỉ IP là 172.17.x.x

Đây chính là là cơ chế tự động tạo IP trong bridge network.


3️⃣ Test kết nối bằng BusyBox – đây là bài test “huyền thoại” của Docker

Để test kết nối với web1 trong môi trường Docker, chúng ta sẽ chạy một container BusyBox tạm thời để test kết nối với web1, sử dụng lệnh sau:

docker run --rm -it busybox

Bên trong BusyBox chúng ta thực hiện các việc sau:

✔️ Kiểm tra IP với lệnh:

ip addr

✔️ Ping đến web1 bằng IP của nó

ping <WEB1_IP_ADDRESS>

Bạn có thể thấy có thể ping đến web1 thành công.

✔️ Tiếp theo chúng ta Ping đến web1 bằng hostname của nó

ping web1

Bạn sẽ thấy không thể ping được đến hostname của web 1, như vậy ping là thất bại.

Các bạn có thể thấy Kết quả ở đây chúng ta không ping được đến web1 bằng hostname của nó. Lý do là bridge network mặc định không hỗ trợ việc phân giải tên miền DNS giữa các containers.

✔️ Và chúng ta có thể Thử truy cập HTTP bằng lệnh wget:

wget <WEB1_IP_ADDRESS>

Sau đó thoát ra với lệnh sau:

exit

Giải thích nhanh – Tư duy về Docker Network

Trong default bridge network, bạn có thể thấy là:

  • Các Containers có thể giao tiếp với nhau qua IP

  • Các Containers KHÔNG thể giao tiếp với nhau bằng hostname

  • Tuy nhiên, một lưu ý cực quan trọng đó là từ máy host của bạn, bạn luôn có thể ping đến tất cả các containers, vì host quản lý toàn bộ các Docker networks.

Docker tạo ra sự đơn giản:

“Containers talk via IP. DNS is optional.”


PHẦN 2 – Custom Bridge Network: Docker DNS xuất hiện ở đây

Như chúng ta đã thấy qua phần vừa rồi thì Default bridge khá hạn chế. Đó là lý do tại sao chúng ta sẽ tạo một bridge network riêng cho các containers chạy ứng dụng của chúng ta, đây là nơi có dịch vụ Docker DNS hỗ trợ cho việc phân giải tên hostname hoạt động một cách đầy đủ.


1️⃣ Để tạo một network mới trong Docker chúng ta có lệnh sau

docker network create test_application

Docker sẽ tạo ra cho chúng ta một mạng bridge mới – hoàn toàn tách biệt với các networks khác đã có sẵn trong Docker.


2️⃣ Chạy web2 trong network mới

Tiếp theo, chúng ta chạy container web2 và chỉ định network test_application với các lệnh sau:
docker run -d --name web2 --network test_application httpd:2.4
docker inspect web2

Kết quả:

  • Khi inspect, bạn sẽ thấy web2 có một IP riêng trong một network mới có tên làtest_application

Như vậy các bạn có thể thấy là Docker đã tạo cho chúng ta một micro-network để chúng ta có thể sử dụng cho các containers của chúng ta.


3️⃣ Và chúng ta sẽ Test kết nối bằng BusyBox trong cùng network

Chạy lệnh sau để tạo một busybox trong test_application network cho việc test kết nối đến web2 của chúng ta:
docker run --rm -it --network test_application busybox

Bên trong BusyBox chúng ta thực hiện các việc sau:

✔️ Đầu tiên chúng ta kiểm tra IP của container này với lệnh:

ip addr

✔️ Sau đó Ping đến web2 bằng IP của nó:

ping <WEB2_IP_ADDRESS>

✔️ Ping đến web2 bằng hostname của nó:

ping web2

Lần này bạn sẽ thấy là ping bằng hostname sẽ thành công, do chúng ta có Docker DNS hoạt động trong custom bridge, có tên là test_application mà chúng ta đã tạo.

✔️ Nếu chúng ta thử wget bằng hostname, sẽ thấy nó works:

wget web2

4️⃣ Thử ping sang default bridge – thất bại (đúng thiết kế)

Bây giờ từ busybox này đang chạy trong test_application network, chúng ta thử ping sang web1 là container đang nằm trong network mặc định.

ping <WEB1_IP_ADDRESS>
wget <WEB1_IP_ADDRESS>

Kết quả: Cho chúng ta thấy không thể ping được, tại sao không ping được?

mỗi một custom bridge chính là một “vùng mạng riêng” và hoàn toàn bị cô lập với các network khác trong Docker.

Có nghĩa là theo mặc định Docker luôn tạo ra các isolation networks, và các networks này là hoàn toàn tách biệt nhau :

“Separate networks should behave like separate universes.”


PHẦN 3 – Host Network: Container sẽ sử dụng host Network

Host network là một mode đặc biệt, có nghĩa là:

  • Container không có IP riêng (không được gán một private IP như 172.x.x.x)

  • Dùng chung network stack với host, có nghĩa là Container dùng luôn IP của host

  • Khi chạy ifconfig hoặc ip addr bên trong container để xem IP của container , do đó bạn sẽ thấy giống hệt host
  • Tốc độ network cực nhanh (Ít latency hơn, Throughput cao hơn, Performance gần như bằng native Linux ) – vì bỏ qua NAT. Còn Bridge network phải đi qua NAT (iptables MASQUERADE)

  • Đây cũng là lý do các workload containers cần tốc độ cao (như Prometheus exporter, load testing tool…) thường chạy bằng host network.

1️⃣ Và bây giờ chúng ta sẽ Chạy web3 sử dụng host network

docker run -d --name web3 --network host httpd:2.4

2️⃣ Sau đó chúng ta Test trực tiếp từ máy host

Các bạn có thể thấy ngay trên chính máy host, bạn có thể truy cập web3 như truy cập một service thông thường:

wget localhost

Vì web3 chạy httpd:2.4 với host network, cách practical nhất để “vào bên trong nó” là dùng lệnh:

docker exec -it web3 /bin/sh

Chúng ta có thể thấy IP của web3 chính là IP của host:

hostname -I


3️⃣ Tiếp theo chúng ta sẽ thử dừng web3 và kiểm tra lại

docker stop web3
wget localhost

Lúc này web3 sẽ không còn phục vụ, sẽ báo lỗi kết nối.


4️⃣ Start lại web3 và kiểm tra tiếp

docker start web3


5️⃣ Test từ BusyBox chạy trong host network

docker run --rm -it --network host busybox

Bên trong BusyBox chúng ta thực hiện các việc sau:

✔️ Truy cập localhost thử test HTTP:

wget localhost

✔️ Sau đó sẽ thử Ping đến web1 và web2:

ping <WEB1_IP_ADDRESS>
ping <WEB2_IP_ADDRESS>

Các bạn có thể thấy vẫn có thể ping được đến Web1 và web2, vì BusyBox đang chạy chung network với host, và host luôn truy cập được tất cả các containers.


Key Insight – Điều quan trọng nhất

Host có thể ping được TẤT CẢ containers, bất kể chúng nằm trong network nào.

Vì host chính là “root” của mọi network Docker.

Solomon Hykes từng nhấn mạnh:

“The host is the source of truth. Everything else is a sandbox.”


Tóm tắt kiến thức

Network Type DNS? Isolation Giao tiếp
Default Bridge Trung bình Ping IP
Custom Bridge ✔️ Cao Ping IP + Name
Host Không tách biệt Thấp Host ⇆ Containers

Nếu bài viết này giúp bạn hiểu rõ hơn về Docker Container Networking – hãy để lại bình luận hoặc chia sẻ để nhiều người khác cũng tiếp cận được nhé.

Bạn cũng có thể:

Theo dõi kênh YouTube của mình: introduction
Đọc thêm các bài viết chuyên sâu trên blog
Đăng ký khóa học của mình để chuẩn bị cho thi chứng chỉ như LPIC, AWS, Azure, cũng như giúp level up kỹ năng thực chiến của bạn!

Cảm ơn bạn đã đọc đến cuối bài.
Hẹn gặp bạn trong bài viết tiếp theo – nơi chúng ta sẽ tiếp tục “mổ xẻ” Docker theo cách đơn giản, trong sáng, và đầy sức mạnh – đúng tinh thần Solomon Hykes cha đẻ của Docker.


#Docker #DevOps #DockerNetworking #Container #BridgeNetwork #HostNetwork #DockerTutorial #Microservices #Linux #Cloud #BusyBox #NetworkingBasics #DockerVietnam #PhuongIT

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *