Sau bài này bạn làm được: giải thích luồng traffic từ container ra internet và từ bên ngoài vào container; debug xung đột cổng khi chạy nhiều compose project; biết khi nào MTU là nguyên nhân gây kết nối kỳ lạ.
Docker thêm lớp network abstraction
Mỗi container mặc định có network namespace riêng — một không gian mạng cô lập với host và với container khác. Kernel tạo “interface ảo” nối container vào bridge.
[Host]
├── eth0: 10.0.1.50/24 → ra ngoài internet
└── docker0 (bridge): 172.17.0.1/16
├── veth123 ←→ [Container A: eth0: 172.17.0.2]
└── veth456 ←→ [Container B: eth0: 172.17.0.3]
docker0 là L2 bridge — các container cùng bridge thấy nhau như cùng LAN.
Bridge network — chế độ mặc định
Khi chạy docker run không chỉ định network, container gắn vào default bridge (docker0):
docker run -d nginx
docker inspect <id> | grep IPAddress
# "IPAddress": "172.17.0.2"
Container có thể nói chuyện với nhau qua IP nội bộ, nhưng không resolve được tên container — đây là hạn chế của default bridge.
Publish port: -p host_port:container_port
docker run -d -p 8080:80 nginx
Docker thêm rule iptables DNAT:
[Internet] → host:8080
↓ iptables DNAT
[Container: 172.17.0.2:80]
[Container ra ngoài]
↓ iptables MASQUERADE (SNAT)
[Host IP: 10.0.1.50] → Internet
Xung đột cổng:
docker run -p 8080:80 app1 # OK
docker run -p 8080:80 app2 # Error: address already in use
Mỗi (host_ip, host_port, protocol) chỉ có một process giữ. Dùng ss -lntp | grep 8080 để tìm ai đang giữ.
User-defined bridge — tốt hơn cho compose
Docker Compose tự tạo user-defined bridge riêng cho mỗi project:
# docker-compose.yml
services:
api:
image: my-api
db:
image: postgres
[my-project_default bridge]
├── api → có thể resolve "db" bằng DNS
└── db → có thể resolve "api" bằng DNS
Container trong cùng user-defined bridge resolve được tên service qua DNS nội bộ Docker — khác với default bridge.
Cô lập giữa compose project:
[project-a_default: 172.20.0.0/16] ── cô lập ── [project-b_default: 172.21.0.0/16]
Mặc định, container project A không reach được container project B trừ khi thêm shared network.
Network modes đặc biệt
# Host network: container dùng chung stack mạng với host
docker run --network host nginx
# nginx sẽ listen trực tiếp trên host:80, không qua NAT
# Lợi: không overhead NAT | Rủi ro: mất cô lập cổng
# None: container không có network interface (trừ loopback)
docker run --network none my-job
# Dùng cho build job cần hoàn toàn offline
MTU — điểm hay bị bỏ qua
Khi chạy Docker bên trong VPC hoặc qua VPN:
VPN tunnel MTU: 1400 byte
Docker default MTU: 1500 byte (kế thừa từ host Ethernet)
Kết quả: gói TCP lớn hơn 1400 byte bị drop hoặc fragment
Triệu chứng: ping nhỏ OK, curl download lớn treo / kết nối ngắt giữa chừng
Xem MTU hiện tại:
ip link show docker0
# 3: docker0: mtu 1500
Cấu hình MTU cho Docker daemon:
// /etc/docker/daemon.json
{
"mtu": 1450
}
Inspect và debug network
# Liệt kê network
docker network ls
# Xem chi tiết: subnet, gateway, container kết nối
docker network inspect bridge
# Xem interface trong container
docker exec <container> ip addr
docker exec <container> ip route
# Test kết nối từ trong container
docker exec <container> nc -vz db 5432
docker exec <container> curl -v http://api:8080/health
Tóm tắt
- Bridge + NAT là mô hình mặc định: container có IP riêng, ra internet qua SNAT.
- Publish port = DNAT rule trên host; xung đột khi hai container cùng port.
- User-defined bridge (Compose) cho DNS tên service — nên dùng thay default bridge.
- MTU là nguyên nhân hay bị bỏ qua khi kết nối kỳ lạ trong VPN/VPC.
Câu hỏi hay gặp
Ping được IP nhưng curl http://tên-service không resolve trên default bridge — vì sao?
Trả lời: Default bridge không có DNS tên container như user-defined network. Dùng docker network create + attach container, hoặc link (lỗi thời), hoặc gọi bằng container name trên user-defined bridge / Compose.
-p 0.0.0.0:5432:5432 vs -p 127.0.0.1:5432:5432 khác nhau thế nào về bảo mật?
Trả lời: 0.0.0.0 publish ra mọi interface (mạng LAN/VPC có thể vào được). 127.0.0.1 chỉ localhost host — an toàn hơn nếu chỉ cần tunnel/port-forward cục bộ.
SSH vào container OK nhưng upload lớn treo (VPN MTU 1400) — kiểm tra gì đầu tiên?
Trả lời: MTU đường đi (host, bridge, VPN): thử giảm MTU Docker/daemon.json, hoặc kiểm tra PMTUD/black hole — triệu chứng điển hình của gói lớn bị drop.
Bài tiếp theo (Giai đoạn III): Mạng trong Kubernetes — container ở quy mô cluster với Service, Ingress và DNS riêng.