Docker容器和服務如此強大的緣由之一是您能夠將它們鏈接在一塊兒,或將它們鏈接到非Docker工做負載。 Docker容器和服務甚至不須要知道它們已部署在Docker上,也沒必要知道它們的對等對象是否也是Docker工做負載。 不管您的Docker主機運行Linux,Windows仍是二者結合,您均可以使用Docker以與平臺無關的方式管理它們。node
本主題定義了一些基本的Docker網絡概念,並幫助您設計和部署應用程序以充分利用這些功能。nginx
Docker的網絡子系統使用驅動程序是可插拔的。默認狀況下存在幾個驅動程序,並提供核心網絡功能:docker
bridge
:默認的網絡驅動程序。 若是您未指定驅動程序,則這是您正在建立的網絡類型。當您的應用程序在須要通訊的獨立容器中運行時,一般會使用網橋網絡。host
:對於獨立容器,去掉容器和Docker主機之間的網絡隔離,直接使用主機的網絡。host
僅可用於Docker 17.06及更高版本上的集羣服務。overlay
:overlay
網絡將多個Docker守護程序鏈接在一塊兒,並使羣集服務可以相互通訊。您還可使用overlay
網絡來促進羣集服務和獨立容器之間或不一樣Docker守護程序上的兩個獨立容器之間的通訊。這種策略消除了在這些容器之間進行操做系統級路由的須要macvlan
:Macvlan網絡容許您將MAC地址分配給容器,使其在網絡上顯示爲物理設備。 Docker守護程序經過其MAC地址將流量路由到容器。 在處理但願直接鏈接到物理網絡而不是經過Docker主機的網絡堆棧進行路由的傳統應用程序時,使用macvlan驅動程序有時是最佳選擇。none
:對於此容器,禁用全部聯網。 一般與自定義網絡驅動程序一塊兒使用。none
不適用於swarm services.這一部分包含三個不一樣的指南,你能夠在不一樣系統上運行他們,可是對於最後兩個,你須要額外的Docker主機運行。shell
儘管overlay網絡一般用於集羣服務,但Docker 17.06及更高版本容許您將overlay網絡用於獨立容器。 這是使用overlay網絡的教程的一部分。安全
在此示例中,您在同一Docker主機上啓動了兩個不一樣的alpine容器,並進行了一些測試以瞭解它們如何相互通訊。 您須要安裝並運行Docker。bash
1.打開一個終端窗口。 在執行其餘任何操做以前,請先列出當前網絡。 若是您從未在此Docker守護程序上添加網絡或初始化羣組,則應該看到如下內容。 您可能會看到不一樣的網絡,但至少應該看到如下內容(網絡ID會有所不一樣):網絡
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
17e324f45964 bridge bridge local
6ed54d316334 host host local
7092879f2cc8 none null local
複製代碼
列出了默認的橋接網絡,以及host
和none
。 後兩個不是徹底成熟的網絡,但用於啓動直接鏈接到Docker守護程序主機的網絡堆棧的容器,或用於啓動不包含網絡設備的容器。 本教程將把兩個容器鏈接到橋接網絡。oop
2.開啓兩個alpine
容器運行ash
,它是Alpine默認的shell,而不是bash
. -dit
標誌的意思是啓動分離的容器(在後臺),交互的(具備鍵入的能力)和TTY(以便您能夠看到輸入和輸出)。因爲您是分開啓動的,所以您不會當即鏈接到該容器。而是將打印容器的ID。 由於你未指定任何--network
選項,因此容器將鏈接到默認的網橋網絡。測試
$ docker run -dit --name alpine1 alpine ash
$ docker run -dit --name alpine2 alpine ash
複製代碼
檢查兩個容器是否確實已啓動:ui
$ 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 alpine1
複製代碼
3.檢查網橋網絡以查看鏈接了哪些容器。
$ 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地址信息(lpine1
爲172.17.0.2
,alpine2
爲172.17.0.3
)
4.容器在後臺運行。 使用docker attach
命令鏈接到alpine1
。
$ docker attach alpine1
/ #
複製代碼
提示符將更改成#
以指示您是容器中的root
用戶。 使用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
內部,經過ping baidu.com
確保您能夠鏈接到互聯網。 -c 2
標誌將命令限制爲兩ping
嘗試。
➜ ~ ping -c 2 baidu.com
PING baidu.com (39.156.69.79): 56 data bytes
64 bytes from 39.156.69.79: icmp_seq=0 ttl=46 time=34.887 ms
64 bytes from 39.156.69.79: icmp_seq=1 ttl=46 time=41.880 ms
--- baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 34.887/38.383/41.880/3.497 ms
➜ ~
複製代碼
6.如今嘗試ping
第二個容器。 首先,經過其IP地址172.17.0.3
對其執行ping
操做:
# 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
並在那裏重複步驟四、5和6,將alpine1
代替爲alpine2
。
8.中止並刪除兩個容器。
$ docker container stop alpine1 alpine2
$ docker container rm alpine1 alpine2
複製代碼
請記住,不建議將默認網橋網絡用於生產。
In this example, we again start two alpine containers, but attach them to a user-defined network called alpine-net which we have already created. These containers are not connected to the default bridge network at all. We then start a third alpine container which is connected to the bridge network but not connected to alpine-net, and a fourth alpine container which is connected to both networks. 在此示例中,咱們再次啓動兩個Alpine
容器,可是將它們附加到咱們已經建立的名爲alpine-net
的用戶定義網絡上。 這些容器根本沒有鏈接到默認橋接網絡。 而後,咱們啓動鏈接到默認網橋網絡但未鏈接alpine-net
的第三個alpine
容器,以及鏈接到兩個網絡的第四個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
命令將第四個容器鏈接到默認橋接網絡上。
$ 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 alpine1
複製代碼
4.再次檢查默認網橋網絡和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": {}
}
]
複製代碼
alpine3
和 alpine4
容器鏈接到了默認的橋接網絡
$ 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
, 和 alpine4
容器鏈接到了alpine-net
網絡.
5。在像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
複製代碼
6.從 alpine1
, 你沒法鏈接到alpine3
, 由於它不在alpine-net
網內.
# ping -c 2 alpine3
ping: bad address 'alpine3'
複製代碼
不只如此,你也不能經過它的IP地址從alpine1
鏈接到alpine3
。查看docker network inspect
的輸出,找到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
複製代碼
使用分離序列CTRL
+ p
CTRL
+ q
(按住CTRL
並鍵入p
後跟q
)從alpine1
分離。
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 www.baidu.com
確保全部的容器均可以鏈接到網絡.由於當前你已經鏈接到了alpine4
,就從它開始,而後退出alpine4
並鏈接到alpine3
(該容器僅僅鏈接到默認的橋接網絡) 進行重試。最後鏈接到alpine1
(它僅僅鏈接到alpine-net
網絡)並進行重試.
# ping -c 2 baidu.com
PING baidu.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
--- baidu.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 baidu.com
PING baidu.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
--- baidu.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 baidu.com
PING baidu.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
--- baidu.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
複製代碼
本系列教程討論集羣服務的網絡。本主題包含四個部份內容,你能夠在不一樣的平臺上運行他們,可是對於最後兩個,你須要一個額外的Docker主機。
overlay network
演示瞭如何在初始化或加入羣集時使用Docker自動爲您設置的默認的overlay network
。 該網絡不是生產系統的最佳選擇。overlay network
顯示瞭如何建立和使用本身的自定義overlay network
來鏈接服務。 建議將其用於生產中運行的服務。overlay network
用於獨立容器顯示瞭如何使用overlay network
在不一樣Docker守護程序上的獨立容器之間進行通訊。overlay network
在獨立容器與羣集服務之間創建通訊。 Docker 17.06及更高版本支持此功能。這些要求您至少有一個單節點羣集,這意味着您已啓動Docker並在主機上運行docker swarm init
。 您也能夠在多節點集羣上運行示例。 最後一個示例須要Docker 17.06或更高版本。
在本例中,您啓動一個alpine
服務,並從各個服務容器的角度分析網絡的特徵。
本教程不討論有關如何實現overlay network的特定於操做系統的詳細信息,而是重點關注從服務的角度來看,overlay network是如何工做的。
本教程須要三臺物理或虛擬Docker主機,它們能夠相互通訊,而且都運行Docker 17.03或更高版本的新安裝。 本教程假定這三臺主機在同一網絡上運行,而且不涉及防火牆。
這些主機將被稱爲manager
, worker-1
,worker-2
.manager
主機即做爲管理者又做爲工做者,這意味着它既要運行服務任務,也要管理swarm. worker-1
和 worker-2
將僅做爲工做者。
若是您沒有三臺主機,一個簡單的解決方案是在雲提供商(例如Amazon EC2)上設置三臺Ubuntu主機,它們所有位於同一網絡上,並容許與該網絡上的全部主機進行全部通訊(使用諸如 EC2安全組),而後按照Ubuntu上Docker Engine-Community的安裝說明進行操做。
在此過程結束時,全部三個Docker主機都將加入集羣,並使用稱爲ingress
的覆蓋網絡鏈接在一塊兒.
1.在manager
上,初始化swarm
集羣。若是主機只有一個網絡接口,--advertise-addr
選項是可選的。
$ docker swarm init --advertise-addr=<IP-ADDRESS-OF-MANAGER>
複製代碼
記下所打印的文本,由於其中包含將用於將worker-1和worker-2加入到羣中的令牌。 將令牌存儲在密碼管理器中是一個好主意。
2.在worker-1
上,加入到swarm
。若是主機只有一個網絡接口,--advertise-addr
選項是可選的.
$ docker swarm join --token <TOKEN> \
--advertise-addr <IP-ADDRESS-OF-WORKER-1> \
<IP-ADDRESS-OF-MANAGER>:2377
複製代碼
3.在worker-2
上,加入到swarm
。若是主機只有一個網絡接口,--advertise-addr
選項是可選的.
$ docker swarm join --token <TOKEN> \
--advertise-addr <IP-ADDRESS-OF-WORKER-2> \
<IP-ADDRESS-OF-MANAGER>:2377
複製代碼
4.在manager
上, 列出全部的節點。這個命令只能在manager上執行。
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
d68ace5iraw6whp7llvgjpu48 * ip-172-31-34-146 Ready Active Leader
nvp5rwavvb8lhdggo8fcf7plg ip-172-31-35-151 Ready Active
ouvx2l7qfcxisoyms8mtkgahw ip-172-31-36-89 Ready Active
複製代碼
您也可使用--filter
標誌按角色進行過濾:
$ docker node ls --filter role=manager
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
d68ace5iraw6whp7llvgjpu48 * ip-172-31-34-146 Ready Active Leader
$ docker node ls --filter role=worker
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
nvp5rwavvb8lhdggo8fcf7plg ip-172-31-35-151 Ready Active
ouvx2l7qfcxisoyms8mtkgahw ip-172-31-36-89 Ready Active
複製代碼
5.列出manager
,worker-1
,worker-2
上全部的網絡,請注意它們如今都有一個叫作ingress
的覆蓋網絡和一個叫docker_gwbridge
的橋接網絡。這裏只展現manager的:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
495c570066be bridge bridge local
961c6cae9945 docker_gwbridge bridge local
ff35ceda3643 host host local
trtnl4tqnc3n ingress overlay swarm
c8357deec9cb none null local
複製代碼
docker_gwbridge
將ingress
網絡鏈接到Docker主機的網絡接口,以便流量能夠往返於羣管理者和工做者。若是建立羣集服務但未指定網絡,則它們將鏈接到ingress
網絡.建議對將一塊兒使用的每一個應用程序或一組應用程序使用單獨的覆蓋網絡。在下一個過程當中,您將建立兩個覆蓋網絡並將服務鏈接到每一個覆蓋網絡。
1.在manager
上,建立一個新的overlay network叫nginx-net
:
$ docker network create -d overlay nginx-net
複製代碼
您無需在其餘節點上建立overlay網絡,由於當其中一個節點開始運行須要該overlay網絡的服務任務時,overlay網絡會自動建立。
2.在manager
上, 建立一個有5個副本的Nginx服務並鏈接到nginx-net
.服務將對外開放80端口。全部服務任務容器均可以在不打開任何端口的狀況下彼此通訊。
服務只能在管理器上建立
$ docker service create \
--name my-nginx \
--publish target=80,published=80 \
--replicas=5 \
--network nginx-net \
nginx
複製代碼
ingress
的默認發佈模式, 在你沒有爲--publish
選項指定一個mode
時使用。這意味着你若是訪問manager
,worker-1
或者worker-2
上的80端口,你將鏈接到5個服務任務中的任何一個的80端口上。即使當前並無任務運行在你訪問的節點上。若是你想使用host
模式發佈端口,你能夠在--publish
選項上增長mode=host
。可是,這種狀況下,你要用--mode global
代替 --replicas=5
, 由於只有一個服務任務能夠綁定到給定節點上的給定端口。
3.運行docker service ls
監視服務啓動進度,這可能須要幾秒鐘。
4.在manage
,worker-1
,worker-2
上檢查nginx-net
網絡. 記住你不須要在worker-1
和worker-2
上手動建立它,由於Docker會給你建立好。輸出會很長,可是隻需注意Containers
和Peers
部分。Containers
列出了全部的從該主機鏈接到overlay網絡的服務任務(或者單獨的容器)。
5.對於manager
,使用docker service inspect my-nginx
檢查服務,並注意有關服務使用的端口和端點的信息。
6.建立一個新的網絡nginx-net-2
, 而後使用這個新的網絡更新服務:
$ docker network create -d overlay nginx-net-2
複製代碼
$ docker service update \
--network-add nginx-net-2 \
--network-rm nginx-net \
my-nginx
複製代碼
7.運行docker service ls
檢查服務已經更新了,而且全部的任務已經從新部署。運行 docker network inspect nginx-net
驗證沒有容器鏈接到它。對nginx-net-2
運行相同的命令,注意全部的服務任務容器都鏈接到它。
overlay網絡在swarn工做節點上是按需自動建立的,他們不會自動刪除
8.清理服務和網絡。 在管理器中,運行如下命令。 管理者將指示工做人員自動刪除網絡。
$ docker service rm my-nginx
$ docker network rm nginx-net nginx-net-2
複製代碼
本教程假設羣集已經設置好,而且您是在一個管理器上。
1.建立用戶定義的覆蓋網絡。
$ docker network create -d overlay my-overlay
複製代碼
2.使用overlay網絡啓動一個服務並將端口80發佈到Docker主機上的8080上
$ docker service create \
--name my-nginx \
--network my-overlay \
--replicas 1 \
--publish published=8080,target=80 \
nginx:latest
複製代碼
3.運行docker network inspect my-overlay
驗證my-nginx
服務任務已經鏈接到它了。經過查看Containers
部分。
4.刪除服務和網絡
$ docker service rm my-nginx
$ docker network rm my-overlay
複製代碼
此示例演示了DNS容器發現-具體地說,是如何使用覆蓋網絡在不一樣Docker守護程序上的獨立容器之間進行通訊。 步驟以下:
host1
上, 初始化節點爲一個swarm(manager).host2
上, 加入該節點到swarm中(做爲工做節點)host1
上,建立一個可鏈接的覆蓋網絡(test-net
)。host1
上,在test-net
上運行一個交互式alpine
容器 (alpine1
)。host2
上,在test-net
上運行一個交互式,可分離的alpine
容器 (alpine2
)。host1
上, 從一個alpine1
會話中,ping alpine2
對於此測試,您須要兩個能夠相互通訊的不一樣Docker主機。 每一個主機必須具備Docker 17.06或更高版本,而且在兩個Docker主機之間打開如下端口:
一種簡單的設置方法是擁有兩個VM(本地或在AWS等雲提供商上),每一個VM均已安裝並正在運行Docker。 若是您使用的是AWS或相似的雲計算平臺,最簡單的配置是使用一個安全組,該安全組打開兩個主機之間的全部傳入端口以及來自客戶端IP地址的SSH端口。
此示例將咱們羣中的兩個節點稱爲host1
和host2
。 此示例還使用Linux主機,可是相同的命令在Windows上也可使用。
1.設置swarm 在host1
上,初始化集羣(若是出現提示,請使用--advertise-addr
指定與集羣中其餘主機通訊的接口的IP地址,例如AWS上的私有IP地址):
$ docker swarm init
Swarm initialized: current node (vz1mm9am11qcmo979tlrlox42) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5g90q48weqrtqryq4kj6ow0e8xm9wmv9o6vgqc5j320ymybd5c-8ex8j0bc40s6hgvy5ui5gl4gy 172.31.47.252:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
複製代碼
在host2
上,按照上述說明加入羣集:
$ docker swarm join --token <your_token> <your_ip_address>:2377
This node joined a swarm as a worker.
複製代碼
若是節點沒法加入羣集,則docker swarm join
命令會超時。 要解決此問題,請在host2
上運行docker swarm leave --force
,驗證您的網絡和防火牆設置,而後重試。
2.在host1
上, 建立一個能夠鏈接的overlay網絡叫test-net
:
$ docker network create --driver=overlay --attachable test-net
uqsof8phj3ak0rq9k86zta6ht
複製代碼
注意返回的NETWORK ID-從host2鏈接到它時,您將再次看到它。
3.在host1
上,啓動一個交互式的容器alpine1
鏈接到test-net
:
$ docker run -it --name alpine1 --network test-net alpine
/ #
複製代碼
4.在host2
上, 羅列出可用的網絡--注意test-net
還不存在:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
ec299350b504 bridge bridge local
66e77d0d0e9a docker_gwbridge bridge local
9f6ae26ccb82 host host local
omvdxqrda80z ingress overlay swarm
b65c952a4b2b none null local
複製代碼
5.On host2
, 以-d
和 (-it
) 的方式啓動一個容器 (alpine2
) 並鏈接到test-net
:
$ docker run -dit --name alpine2 --network test-net alpine
fb635f5ece59563e7b8b99556f816d24e6949a5f6a5b1fbd92ca244db17a4342
複製代碼
自動DNS容器發現僅適用於惟一的容器名稱。
6.在host2
上, 驗證 test-net
網絡已經建立(和host1
上的test-net
有同樣的NETWORK ID):
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
...
uqsof8phj3ak test-net overlay swarm
複製代碼
7.在host1
上, 在alpine1
的交互終端內ping alpine2
:
/ # ping -c 2 alpine2
PING alpine2 (10.0.0.5): 56 data bytes
64 bytes from 10.0.0.5: seq=0 ttl=64 time=0.600 ms
64 bytes from 10.0.0.5: seq=1 ttl=64 time=0.555 ms
--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.555/0.577/0.600 ms
複製代碼
兩個容器與鏈接兩個主機的覆蓋網絡通訊。若是你在host2
主機上運行另外一個alpine容器,而不detached.你能夠從host2
ping alpine1
(這裏咱們增長了容器自動清理的選項):
$ docker run -it --rm --name alpine3 --network test-net alpine
/ # ping -c 2 alpine1
/ # exit
複製代碼
8.在host1
上, 關閉alpine1
的會話 (這將中止容器):
/ # exit
複製代碼
9.清理你的容器和網絡 您必須在每一個主機上獨立中止和刪除容器,由於Docker守護程序是獨立運行的,而且它們是獨立的容器。 您只須要刪除host1
上的網絡,由於當您中止host2
上的alpine2
時,test-net
就會消失。
在host2
上,中止alpine2
,檢查test-net
已經刪除,而後刪除alpine2
:
$ docker container stop alpine2
$ docker network ls
$ docker container rm alpine2
複製代碼
在 host1
上, 刪除 alpine1
and test-net
:
$ docker container rm alpine1
$ docker network rm test-net
複製代碼
本例須要Docker 17.06或更高版本。
在此示例中,您在同一Docker主機上啓動了兩個不一樣的alpine1
容器,並進行了一些測試以瞭解它們如何相互通訊。 您須要安裝並運行Docker。
1.打開一個終端窗口。 在執行其餘任何操做以前,請先列出當前網絡。 若是您從未在此Docker守護程序上添加網絡或初始化羣組,則應該看到如下內容。 您可能會看到不一樣的網絡,但至少應該看到如下內容(網絡ID會有所不一樣):
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
17e324f45964 bridge bridge local
6ed54d316334 host host local
7092879f2cc8 none null local
複製代碼
列出了默認的橋接網絡,以及host
和none
。 後兩個不是徹底成熟的網絡,但用於啓動直接鏈接到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 alpine1
複製代碼
3.檢查網橋網絡以查看鏈接了哪些容器。
$ 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
/ #
複製代碼
提示符將更改成#
以指示您是容器中的root
用戶。 使用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
內部,經過ping baidu.com
確保您能夠鏈接到互聯網。-c 2
標誌將命令限制兩次兩次ping操做。
# ping -c 2 baidu.com
PING baidu.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
--- baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 9.841/9.869/9.897 ms
複製代碼
7.如今嘗試ping第二個容器。 首先,經過其IP地址172.17.0.3
對其執行ping操做:
# 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
並在那裏重複步驟四、5和6,將alpine1
代替爲alpine2
。
8.中止並刪除容器;
$ docker container stop alpine1 alpine2
$ docker container rm alpine1 alpine2
複製代碼
請記住,不建議將默認網橋網絡用於生產。