Phần 14 – Bridge network trong docker

By | 30 January, 2020

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ànhUbuntu 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à bridgehostcũ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

mạng cầu docker

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:

mạng cầu docker

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: [email protected]: <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à alpine1alpine2alpine3và alpine4 làm cho các thiết lập mạng như sau:

ContainerDocker Network
alpine1alpine-net
alpine2alpine-net
alpine3docker0
alpine4alpine-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: [email protected]: <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: [email protected]: <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:

tùy chỉnh mạng cầu docker

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:

  1. 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
  2. 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:

  1. Trong docker0 container dưới bridge không thể giao tiếp với nhau thông qua tên miền
  2. 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.

Leave a Reply

avatar
  Subscribe  
Notify of