Bài viết này giới thiệu Docker Bridge Network và cách thức hoạt động
Giới thiệu môi trường
Các xét nghiệm sau đây sẽ được thực hiện trong các môi trường sau:
- Hệ điều hành
Ubuntu 18.04 - Docker:
18.03.1-ce
Xem trạng thái Mạng Docker hiện tại
Sau đây là trạng thái mạng docker ngay sau khi docker 18.03.1 được cài đặt trên Ubuntu 18.04:
$ docker network ls NETWORK ID NAME DRIVER SCOPE a1c7b6f80389 bridge bridge local dc2f51e1056f host host local f28460d3a620 none null local
Như có thể thấy từ trên, chỉ cần cài đặt Docker Linux máy chủ, docker sẽ tạo ra 3 loại network mặc định đó là bridge, hostcũng null.
Sau đây sẽ giới thiệu chế độ hoạt động của mạng cầu một cách cẩn thận.
Tổng quát
Hãy bắt đầu với khái niệm Docker Bridge Network:
- Bridge Network tạo ra một cây cầu trên Docker Host để đạt được mục đích cho phép container kết nối với bên ngoài. Thông qua cây cầu này, các container của cùng một cây cầu có thể giao tiếp với nhau và trình điều khiển cầu docker sẽ tự động được đặt trên máy chủ. Quy tắc tương ứng (iptables, không gian tên mạng) cho phép mạng của bộ chứa được sử dụng chính xác.
- Bridge Network được sử dụng để xử lý giao tiếp giữa các container đang chạy trên một trình docker daemon duy nhất. Nếu bạn muốn giao tiếp các container trên nhiều server khác nhau, bạn phải sử dụng overlay network.
Hình dưới đây là kiến trúc của Bridge Network

Sử dụng Bridge Network (docker0)
Sau khi docker được cài đặt, trên thực tế docker đã chuẩn bị một cây cầu docker0 cho chúng ta như một cây cầu phần mềm bên ngoài của container. Ví dụ sau đây trước tiên sẽ sử dụng docker0 để thử nghiệm.
Tạo container
Đầu tiên tạo Container cần thiết và xem trạng thái network:
# tạo alpine linux container 1 (alpine1)
$ docker run -dit --name alpine1 alpine ash
b75464efd30bf09e118450de2abaeb35549e732bac5805671f1e6e97cd970897
# tạo alpine linux container 2 (alpine2)
$ docker run -dit --name alpine2 alpine ash
16aa4a102b14de3e151cb5e19522925bb4e143034d5b2aac4ce239c79716b703
# kiểm tra software bridge status
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024284431eec no vethbddc381
vethee2a421
# xem trạng thái docker bridge network
$ docker network inspect bridge
[
{
# docker network đang sử dụng là "bridge"
"Name": "bridge",
"Id": "a1c7b6f8038999f034b8e64ae66885fa8094a020a306ce4f5b5692d7230890b0",
"Created": "2018-07-09T01:23:03.98371109Z",
"Scope": "local",
# driver đang dùng là bridge
"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": {
# tên container alpine2 (tương ứng với container ID)
"16aa4a102b14de3e151cb5e19522925bb4e143034d5b2aac4ce239c79716b703": {
"Name": "alpine2",
"EndpointID": "4dc3947583ece828dd4371351501e7d0ba9fa149ac5373ea4ddb9466d333b85d",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
# container alpine1 (tương ứng với container ID)
"b75464efd30bf09e118450de2abaeb35549e732bac5805671f1e6e97cd970897": {
"Name": "alpine1",
"EndpointID": "ea0138a2c51812f3f142db086e1690f6696e36ff972c826727be30e3c8b8cb41",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"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",
# tên bridge được sử dụng
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
Kiến trúc mạng hiện tại trở thành như sau:

Kiểm tra network container
Sau khi hiểu kiến trúc mạng ở trên, hãy kiểm tra mạng container:
# Xem container IP
$ docker exec -it alpine1 ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# Kiểm tra kết nối
$ docker exec -it alpine1 ping -c 3 www.google.com
PING www.google.com (216.58.200.228): 56 data bytes
64 bytes from 216.58.200.228: seq=0 ttl=54 time=2.112 ms
64 bytes from 216.58.200.228: seq=1 ttl=54 time=2.166 ms
64 bytes from 216.58.200.228: seq=2 ttl=54 time=2.417 ms
# Kiểm tra có mạng với container khác (dùng IP)
$ docker exec -it alpine1 ping -c 3 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.121 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.071 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.068 ms
# Kiểm tra có mạng với container khác (dùng domain name) => không connect được
$ docker exec -it alpine1 ping -c 3 alpine2
ping: bad address 'alpine2'
Từ thử nghiệm trên, chúng ta có thể thấy rằng trên thực tế, hai container docker0 có thể giao tiếp với nhau vì chúng sử dụng cùng một cây cầu ( ), nhưng chúng không thể sử dụng tên miền, có nghĩa là chúng không biết nhau.
Tạo một Bridge Network
Docker Network tùy chỉnh
Điều này cũng là việc sử dụng điều khiển Bridge Network, nhưng thông qua docker network create việc tạo một Bridge Network mới, ở đây tên là alpine-net:
$ docker network create --driver bridge alpine-net
2575acac8e781004cb0dc5c5b020c0252a4bc4cdf18dfc661fe3ffcde30fd0b2
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
2575acac8e78 alpine-net bridge local
a1c7b6f80389 bridge bridge local
dc2f51e1056f host host local
f28460d3a620 none null local
$ docker network inspect alpine-net
[
{
# docker bridge network đã được đổi tên
"Name": "alpine-net",
# ID của bridge
"Id": "2575acac8e781004cb0dc5c5b020c0252a4bc4cdf18dfc661fe3ffcde30fd0b2",
"Created": "2018-07-09T03:05:05.505539609Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
# đã thêm một software bridge
$ brctl show
bridge name bridge id STP enabled interfaces
br-2575acac8e78 8000.0242a2569c8d no
docker0 8000.024284431eec no
# Cái bridge được sử dụng là 172.18.0.1/16 khác biệt với docker0
$ ip a
.... ()
14: br-2575acac8e78: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:a2:56:9c:8d brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-2575acac8e78
valid_lft forever preferred_lft forever
Có thể thấy từ các kết quả trên, mạng docker mới được tạo ( alpine-net) sẽ được phân bổ để sử dụng một phân đoạn mạng khác, khác với docker0 ban đầu.
Tạo container
Ở đây để xây dựng tổng cộng bốn container, cụ thể là alpine1, alpine2, alpine3và alpine4 làm cho các thiết lập mạng như sau:
| Container | Docker Network |
|---|---|
| alpine1 | alpine-net |
| alpine2 | alpine-net |
| alpine3 | docker0 |
| alpine4 | alpine-net + docker0 |
Và hoàn thành nó với các hướng dẫn sau:
# tạo container,sử dụng alpine-net $ docker run -dit --name alpine1 --network alpine-net alpine ash 010ba5c3e71a723f8c980bb00bb87c97bc41b073163415705006ce5d0071e97c # tạo container,sử dụng alpine-net $ docker run -dit --name alpine2 --network alpine-net alpine ash aecb66274c3b3ec9109ff4eaa582ad4708ed871428d3b4894f9d04330aabcbc4 # tạo container,sử dụng default bridge docker0 $ docker run -dit --name alpine3 alpine ash 3c602d26fcdcc8c0145d4d2d159b20b5b760c1b74393c7b5f7be060f4f8822ac # tạo container,sử dụng alpine-net $ docker run -dit --name alpine4 --network alpine-net alpine ash 83133e6103d63513116e0fb791efea64b016424ca73357ba3fed41b7ea92df95 # chỉnh sử alpine4 connect tới default bridge docker0 $ docker network connect bridge alpine4
Sau đó, đảm bảo rằng các cài đặt mạng có liên quan được thiết lập chính xác:
# Show veth device
$ brctl show
bridge name bridge id STP enabled interfaces
br-2575acac8e78 8000.0242a2569c8d no veth19aee42
veth403e609
veth439dc39
docker0 8000.024284431eec no veth1c78e99
veth9857cc8
# Xem docker bridge - bridge(docker0)
$ docker network inspect bridge
[
{
# tên docker network
"Name": "bridge",
"Id": "a1c7b6f8038999f034b8e64ae66885fa8094a020a306ce4f5b5692d7230890b0",
"Created": "2018-07-09T01:23:03.98371109Z",
"Scope": "local",
#driver là bridge
"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": {
# Đây là mạng được sử dụng bởi alpine3 (tương ứng với ID container ở trên)
"3c602d26fcdcc8c0145d4d2d159b20b5b760c1b74393c7b5f7be060f4f8822ac": {
"Name": "alpine3",
"EndpointID": "7bd6ae1d8a28a554f57f9937953716cc5f62ea8bd669fc744d3aeffacf05f3c1",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
# Đây là mạng được sử dụng bởi alpine4 (tương ứng với ID container ở trên)
"83133e6103d63513116e0fb791efea64b016424ca73357ba3fed41b7ea92df95": {
"Name": "alpine4",
"EndpointID": "2bb63005cf4bcb037d644ab230023e65e8ee9e00cf4d98b3fcf9526c14790492",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
"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": {}
}
]
# xem docker bridge - alpine-net
$ docker network inspect alpine-net
[
{
# tên docker network
"Name": "alpine-net",
"Id": "2575acac8e781004cb0dc5c5b020c0252a4bc4cdf18dfc661fe3ffcde30fd0b2",
"Created": "2018-07-09T03:05:05.505539609Z",
"Scope": "local",
# driver là bridge
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
# Đây là mạng được sử dụng bởi alpine1 (tương ứng với ID container ở trên)
"010ba5c3e71a723f8c980bb00bb87c97bc41b073163415705006ce5d0071e97c": {
"Name": "alpine1",
"EndpointID": "f1357dd263dea947c4cd203fd8031be40fae4840f6994dd5e11d6790a038569c",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
# Đây là mạng được sử dụng bởi alpine4 (tương ứng với ID container ở trên)
"83133e6103d63513116e0fb791efea64b016424ca73357ba3fed41b7ea92df95": {
"Name": "alpine4",
"EndpointID": "cf6bb33270eca6d40d4d953cea49302d210bc8ba995f04cdcf138344d5378d2f",
"MacAddress": "02:42:ac:12:00:04",
"IPv4Address": "172.18.0.4/16",
"IPv6Address": ""
},
# Đây là mạng được sử dụng bởi alpine2 (tương ứng với ID container ở trên)
"aecb66274c3b3ec9109ff4eaa582ad4708ed871428d3b4894f9d04330aabcbc4": {
"Name": "alpine2",
"EndpointID": "28a237e9fe55f133459140c9e5265470e34baeec43c2c0f6c32d5d539b694403",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
Vì alpine4 được kết nối cụ thể với hai mạng, hãy kiểm tra trạng thái mạng của alpine4:
# Như có thể thấy từ output bên dưới, vì alpine4 đã nhận được hai bridge nên hai card mạng sẽ được hiển thị.
$ docker exec -it alpine4 ip a
..... (more)
21: eth0@if22: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:12:00:04 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.4/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
23: eth1@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth1
valid_lft forever preferred_lft forever
Kiến trúc mạng hiện tại trở thành như sau:

Kiểm tra mạng container
Cuối cùng, hãy kiểm tra kết nối giữa các container:
# Kiểm tra giao tiếp với alpine2 $ docker exec -it alpine1 ping -c 2 alpine2 PING alpine2 (172.18.0.3): 56 data bytes 64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.095 ms 64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.076 ms --- alpine2 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.076/0.085/0.095 ms # Kiểm tra giao tiếp với alpine4 $ docker exec -it alpine1 ping -c 2 alpine4 PING alpine4 (172.18.0.4): 56 data bytes 64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.145 ms 64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.102 ms --- alpine4 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.102/0.123/0.145 ms # Kiểm tra giao tiếp với alpine3 $ docker exec -it alpine1 ping -c 2 alpine3 ping: bad address 'alpine3' # Kiểm tra giao tiếp với alpine3 bằng IP $ docker exec -it alpine1 ping -c 2 172.17.0.2 PING 172.17.0.2 (172.17.0.2): 56 data bytes --- 172.17.0.2 ping statistics --- 2 packets transmitted, 0 packets received, 100% packet loss # Kiểm tra giao tiếp với alpine1 (riêng) $ docker exec -it alpine1 ping -c 2 alpine1 PING alpine1 (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.052 ms 64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.079 ms --- alpine1 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.052/0.065/0.079 ms # thử connect ra ngoài $ docker exec -it alpine1 ping -c 2 www.google.com PING www.google.com (172.217.160.68): 56 data bytes 64 bytes from 172.217.160.68: seq=0 ttl=53 time=7.252 ms 64 bytes from 172.217.160.68: seq=1 ttl=53 time=7.329 ms --- www.google.com ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 7.252/7.290/7.329 ms
Các kết luận sau đây có thể được rút ra từ các thử nghiệm trên:
- Trong mạng docker được tạo, container có thể giao tiếp với các container khác trong cùng mạng docker thông qua tên miền
- Các mạng container giữa các mạng docker khác nhau được cách ly và không thể giao tiếp với nhau, cho dù thông qua tên miền hoặc IP
Kết luận đầu tiên là bởi vì docker sẽ cung cấp automatic service discovery cho mạng docker tự tạo , để các container có thể giao tiếp với nhau thông qua tên
Ngoài ra, nếu cùng lúc docker0 với alpine-net hai Bridge Network được dùng cùng lúc bởi alpine4 thực hiện các bài kiểm tra trên container thì kết quả là gì?
# Có thể giao tiếp với container (alpine1) dưới bridge alpine-net theo name $ docker exec -it alpine4 ping -c 2 alpine1 PING alpine1 (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.093 ms 64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.077 ms --- alpine1 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.077/0.085/0.093 ms # Không thể liên lạc với container (alpine3) dưới bridge docker0 theo name $ docker exec -it alpine4 ping -c 2 alpine3 ping: bad address 'alpine3' # Nhưng vẫn có thể giao tiếp với container (alpine3) dùng docker0 qua IP $ docker exec -it alpine4 ping -c 2 172.17.0.2 PING 172.17.0.2 (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.140 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.092 ms --- 172.17.0.2 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.092/0.116/0.140 ms # kiểm tra connect ra ngoài $ docker exec -it alpine4 ping -c 2 www.google.com PING www.google.com (172.217.160.68): 56 data bytes 64 bytes from 172.217.160.68: seq=0 ttl=53 time=7.429 ms 64 bytes from 172.217.160.68: seq=1 ttl=53 time=7.361 ms --- www.google.com ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 7.361/7.395/7.429 ms
Các kết luận sau đây có thể được rút ra từ các thử nghiệm trên alpine4:
- Trong
docker0container dưới bridge không thể giao tiếp với nhau thông qua tên miền - Bạn có thể sử dụng giao tiếp thông qua IP
Với các kết quả kiểm tra sau, nếu bạn muốn sử dụng tên miền để xử lý giao tiếp giữa các container, bạn phải nhớ thiết lập mạng docker mới để xử lý nó để có thể giao tiếp bình thường.
