Docker 之 橋接網絡 (二)

參考:https://docs.docker.com/network/network-tutorial-standalone/

一、與獨立容器聯網

本系列教程討論獨立Docker容器的連網。要使用羣集服務聯網,請參閱使用羣集服務聯網。如果您需要了解更多關於Docker網絡的內容,請參閱概述。

本主題包括三個不同的教程。您可以在Linux、Windows或Mac上運行它們,但是對於最後兩個,您需要在其他地方運行第二個Docker主機。

  • 使用默認網橋演示如何使用Docker爲您自動設置的默認網橋。這個網絡不是生產系統的最佳選擇。
  • 使用用戶定義的橋接網絡顯示如何創建和使用您自己的自定義橋接網絡,以連接運行在相同Docker主機上的容器。對於在生產環境中運行的獨立容器,建議這樣做。

雖然覆蓋網絡通常用於羣服務,Docker 17.06和更高版本允許你使用一個覆蓋網絡用於獨立容器。這是覆蓋網絡使用教程的一部分。

 

二、使用默認橋接網絡

在本例中,您將在同一個Docker主機上啓動兩個不同的alpine容器,並進行一些測試,以瞭解它們之間如何通信。您需要安裝並運行Docker。

1、打開終端窗口。在做任何其他事情之前,請先列出當前的網絡。如果您從未在這個Docker守護進程上添加過網絡或初始化過集羣,那麼應該看看以下內容。你可能會看到不同的網絡,但你至少應該看到這些(網絡id將是不同的):

$ docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
17e324f45964        bridge              bridge              local
6ed54d316334        host                host                local
7092879f2cc8        none                null                local

列出了默認的網橋網絡,以及主機和非主機。後兩個不是完全成熟的網絡,但用於啓動直接連接到Docker守護進程主機的網絡堆棧的容器,或啓動沒有網絡設備的容器。本教程將把兩個容器連接到橋接網絡。

2、啓動兩個運行ash的alpine容器,這是alpine的默認shell,而不是bash。-dit 標誌意味着啓動分離的容器(在後臺)、交互的容器(可以輸入)和TTY容器(可以看到輸入和輸出)。由於您正在啓動它,所以不會立即連接到容器。相反,將打印容器的ID。因爲沒有指定任何--network 標誌,所以容器連接到默認網橋網絡。

$ docker run -dit --name alpine1 alpine ash

$ docker run -dit --name alpine2 alpine ash

檢查兩個容器是否都已啓動:

$ docker container ls

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
602dbf1edc81        alpine              "ash"               4 seconds ago       Up 3 seconds                            alpine2
da33b7aa74b0        alpine              "ash"               17 seconds ago      Up 16 seconds    

檢查橋樑網絡,看看有什麼容器連接到它。

$ docker network inspect bridge

[
    {
        "Name": "bridge",
        "Id": "17e324f459648a9baaea32b248d3884da102dde19396c25b30ec800068ce6b10",
        "Created": "2017-06-22T20:27:43.826654485Z",
        "Scope": "local",
        "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,
        "Containers": {
            "602dbf1edc81813304b6cf0a647e65333dc6fe6ee6ed572dc0f686a3307c6a2c": {
                "Name": "alpine2",
                "EndpointID": "03b6aafb7ca4d7e531e292901b43719c0e34cc7eef565b38a6bf84acf50f38cd",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "da33b7aa74b0bf3bda3ebd502d404320ca112a268aafe05b4851d1e3312ed168": {
                "Name": "alpine1",
                "EndpointID": "46c044a645d6afc42ddd7857d19e9dcfb89ad790afb5c239a35ac0af5e8a5bc5",
                "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",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

在頂部,列出了關於橋接網絡的信息,包括Docker主機和橋接網絡之間網關的IP地址(172.17.0.1)。在Containers鍵下,列出了每個連接的容器及其IP地址信息(alpine1爲172.17.0.2,alpine2爲172.17.0.3)。

 

4、容器在後臺運行。使用docker attach命令連接到alpine1。

$ docker attach alpine1

/ #

提示符變爲#,表示您是容器中的根用戶。使用ip addr show命令來顯示alpine1的網絡接口,因爲他們從容器內查看:

# ip addr show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
27: eth0@if28: <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 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link
       valid_lft forever preferred_lft forever

第一個接口是環回設備。現在先忽略它。注意,第二個接口的IP地址是172.17.0.2,這與前面步驟中顯示的alpine1的地址相同。

 

5、在alpine1內部,確保你可以通過點擊google.com連接到互聯網。- c2標誌將該命令限制爲兩次ping嘗試。

# ping -c 2 google.com

PING google.com (172.217.3.174): 56 data bytes
64 bytes from 172.217.3.174: seq=0 ttl=41 time=9.841 ms
64 bytes from 172.217.3.174: seq=1 ttl=41 time=9.897 ms

--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 9.841/9.869/9.897 ms

6、現在嘗試ping第二個容器。首先,通過它的IP地址ping它,172.17.0.3:

# ping -c 2 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.086 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.094 ms

--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.086/0.090/0.094 ms

  這成功。接下來,嘗試按容器名稱ping alpine2容器。這將會失敗。

# ping -c 2 alpine2

ping: bad address 'alpine2'

7、使用分離序列,CTRL + p CTRL + q(按住CTRL並鍵入p後面跟q)從alpine1上分離,如果你願意,連接到alpine2上,重複步驟4、5、          6,用alpine1替換alpine2。

8、停止並移除兩個容器。

$ docker container stop alpine1 alpine2
$ docker container rm alpine1 alpine2

請記住,不建議在生產環境中使用缺省網橋網絡。要了解用戶定義的橋接網絡,請繼續學習下一教程。

 

二、 使用自定義的網橋網絡

在本例中,我們再次啓動兩個alpine容器,但將它們附加到一個名爲alpine-net的用戶定義網絡,我們已經創建了這個網絡。這些容器根本沒有連接到默認的bridge網絡。然後,我們開始第三個alpine 集裝箱連接到bridge網絡,但沒有連接到alpine-net網絡,和第四個alpine 集裝箱連接到這兩個網絡。

1、創建alpine-net網絡。您不需要 --driver bridge 標誌,因爲它是默認的,但是這個例子展示瞭如何指定它。

$ docker network create --driver bridge alpine-net

2、列出docker 的網絡

$ docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
e9261a8c9a19        alpine-net          bridge              local
17e324f45964        bridge              bridge              local
6ed54d316334        host                host                local
7092879f2cc8        none                null                local

檢查alpine-net網絡。這顯示了它的IP地址和沒有容器連接到它的事實:

$ docker network inspect alpine-net

[
    {
        "Name": "alpine-net",
        "Id": "e9261a8c9a19eabf2bf1488bf5f208b99b1608f330cff585c273d39481c9b0ec",
        "Created": "2017-09-25T21:38:12.620046142Z",
        "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,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

注意,這個網絡的網關是172.18.0.1,而默認橋接網絡的網關是172.17.0.1。確切的IP地址可能是不同的系統。

3、創建四個容器。注意 --network 標誌。在 docker run 命令期間,您只能連接到一個網絡,因此您需要在以後使用docker network connect 將alpine4連接到 bridge 網絡。

$ docker run -dit --name alpine1 --network alpine-net alpine ash

$ docker run -dit --name alpine2 --network alpine-net alpine ash

$ docker run -dit --name alpine3 alpine ash

$ docker run -dit --name alpine4 --network alpine-net alpine ash

$ docker network connect bridge alpine4

 確認所有容器都在運行:

$ docker container ls

CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
156849ccd902        alpine              "ash"               41 seconds ago       Up 41 seconds                           alpine4
fa1340b8d83e        alpine              "ash"               51 seconds ago       Up 51 seconds                           alpine3
a535d969081e        alpine              "ash"               About a minute ago   Up About a minute                       alpine2
0a02c449a6e9        alpine              "ash"               About a minute ago   Up About a minute        

再次檢查bridge 網絡和 alpine-net 網絡

$ docker network inspect bridge

[
    {
        "Name": "bridge",
        "Id": "17e324f459648a9baaea32b248d3884da102dde19396c25b30ec800068ce6b10",
        "Created": "2017-06-22T20:27:43.826654485Z",
        "Scope": "local",
        "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,
        "Containers": {
            "156849ccd902b812b7d17f05d2d81532ccebe5bf788c9a79de63e12bb92fc621": {
                "Name": "alpine4",
                "EndpointID": "7277c5183f0da5148b33d05f329371fce7befc5282d2619cfb23690b2adf467d",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "fa1340b8d83eef5497166951184ad3691eb48678a3664608ec448a687b047c53": {
                "Name": "alpine3",
                "EndpointID": "5ae767367dcbebc712c02d49556285e888819d4da6b69d88cd1b0d52a83af95f",
                "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",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

Containers alpine3 and alpine4 are connected to the bridge network.

$ docker network inspect alpine-net

[
    {
        "Name": "alpine-net",
        "Id": "e9261a8c9a19eabf2bf1488bf5f208b99b1608f330cff585c273d39481c9b0ec",
        "Created": "2017-09-25T21:38:12.620046142Z",
        "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,
        "Containers": {
            "0a02c449a6e9a15113c51ab2681d72749548fb9f78fae4493e3b2e4e74199c4a": {
                "Name": "alpine1",
                "EndpointID": "c83621678eff9628f4e2d52baf82c49f974c36c05cba152db4c131e8e7a64673",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "156849ccd902b812b7d17f05d2d81532ccebe5bf788c9a79de63e12bb92fc621": {
                "Name": "alpine4",
                "EndpointID": "058bc6a5e9272b532ef9a6ea6d7f3db4c37527ae2625d1cd1421580fd0731954",
                "MacAddress": "02:42:ac:12:00:04",
                "IPv4Address": "172.18.0.4/16",
                "IPv6Address": ""
            },
            "a535d969081e003a149be8917631215616d9401edcb4d35d53f00e75ea1db653": {
                "Name": "alpine2",
                "EndpointID": "198f3141ccf2e7dba67bce358d7b71a07c5488e3867d8b7ad55a4c695ebb8740",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

容器 alpine1, alpine2, and alpine4 are  連接到  alpine-net 網絡.

6、在用戶定義的網絡(如alpine-net)上,容器不僅可以通過IP地址進行通信,還可以將容器名稱解析爲IP地址。這種功能稱爲自動服務發現。讓我們連接到alpine1並測試一下。alpine1應該能夠解析alpine2和alpine4(以及alpine1本身)到IP地址。

$ docker container attach 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.085 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.090 ms

--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.085/0.087/0.090 ms

# 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.076 ms
64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.091 ms

--- alpine4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.076/0.083/0.091 ms

# 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.026 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.054 ms

--- alpine1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.026/0.040/0.054 ms

從alpine1,您應該根本不能連接到alpine3,因爲它不在alpine-net網絡上。

# ping -c 2 alpine3

ping: bad address 'alpine3'

不僅如此,你也不能通過它的IP地址從alpine1連接到alpine3。查看docker網絡檢查橋接網絡的輸出,找到alpine3的IP地址:172.17.0.2,嘗試ping它。

# 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

 使用分離序列從alpine1中分離,並按CTRL + p CTRL + q(按住CTRL並鍵入p和q)。

7、請記住,alpine4同時連接到默認橋接網絡和alpine-net。它應該能夠到達所有其他容器。但是,您需要通過它的IP地址來訪問alpine3。附加到它並運行測試。

$ docker container attach 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.074 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.082 ms

--- alpine1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.074/0.078/0.082 ms

# 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.075 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.080 ms

--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.075/0.077/0.080 ms

# ping -c 2 alpine3
ping: bad address 'alpine3'

# 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.089 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms

--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.075/0.082/0.089 ms

# 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.033 ms
64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.064 ms

--- alpine4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.033/0.048/0.064 ms

8、作爲最後的測試,確保你的容器都能通過ping google.com連接到互聯網。你已經連接到alpine4,所以從那裏開始嘗試。接下來,從alpine4斷開並連接到alpine3(它只連接到橋接網絡),然後重試。最後,連接到alpine1(它只連接到alpine-net網絡),然後重試。

# ping -c 2 google.com

PING google.com (172.217.3.174): 56 data bytes
64 bytes from 172.217.3.174: seq=0 ttl=41 time=9.778 ms
64 bytes from 172.217.3.174: seq=1 ttl=41 time=9.634 ms

--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 9.634/9.706/9.778 ms

CTRL+p CTRL+q

$ docker container attach alpine3

# ping -c 2 google.com

PING google.com (172.217.3.174): 56 data bytes
64 bytes from 172.217.3.174: seq=0 ttl=41 time=9.706 ms
64 bytes from 172.217.3.174: seq=1 ttl=41 time=9.851 ms

--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 9.706/9.778/9.851 ms

CTRL+p CTRL+q

$ docker container attach alpine1

# ping -c 2 google.com

PING google.com (172.217.3.174): 56 data bytes
64 bytes from 172.217.3.174: seq=0 ttl=41 time=9.606 ms
64 bytes from 172.217.3.174: seq=1 ttl=41 time=9.603 ms

--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 9.603/9.604/9.606 ms

CTRL+p CTRL+q

9、停止並移除所有容器和alpine-net網絡。

$ docker container stop alpine1 alpine2 alpine3 alpine4

$ docker container rm alpine1 alpine2 alpine3 alpine4

$ docker network rm alpine-net

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章