獨立容器的網路設定
本系列教學課程將探討獨立 Docker 容器的網路設定。關於叢集服務的網路設定,請參閱叢集服務的網路設定。如果您需要更深入了解 Docker 網路,請參閱概觀。
本主題包含兩個不同的教學課程。您可以在 Linux、Windows 或 Mac 上執行每個教學課程,但最後一個教學課程需要在其他地方執行第二個 Docker 主機。
使用預設橋接網路示範如何使用 Docker 自動為您設定的預設
bridge
網路。此網路並非生產系統的最佳選擇。使用使用者定義的橋接網路說明如何建立和使用您自己的自訂橋接網路,以連線在同一個 Docker 主機上執行的容器。建議在生產環境中執行的獨立容器使用此網路。
雖然 覆蓋網路 通常用於叢集服務,但您也可以將覆蓋網路用於獨立容器。這部分包含在 使用覆蓋網路的教學課程 中。
使用預設橋接網路
在此範例中,您將在同一個 Docker 主機上啟動兩個不同的 alpine
容器,並進行一些測試以了解它們之間如何通訊。您需要安裝並執行 Docker。
開啟終端機視窗。在執行任何操作之前,請先列出目前的網路。如果您從未在此 Docker Daemon 上新增網路或初始化叢集,您應該會看到以下內容。您可能會看到不同的網路,但您至少應該看到這些(網路 ID 將會不同)
$ docker network ls NETWORK ID NAME DRIVER SCOPE 17e324f45964 bridge bridge local 6ed54d316334 host host local 7092879f2cc8 none null local
除了
host
和none
之外,還會列出預設的bridge
網路。後兩者不是完整的網路,而是用於啟動直接連線到 Docker Daemon 主機網路堆疊的容器,或用於啟動沒有網路裝置的容器。本教學課程會將兩個容器連線到bridge
網路。啟動兩個執行
ash
的alpine
容器,這是 Alpine 的預設 shell,而不是bash
。-dit
旗標表示以分離模式(在背景中)、互動模式(能夠輸入)和 TTY(可以看到輸入和輸出)啟動容器。由於您是以分離模式啟動它,因此您不會立即連線到容器。相反的,將會印出容器的 ID。因為您沒有指定任何--network
旗標,所以容器會連線到預設的bridge
網路。$ 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
檢查
bridge
網路以查看哪些容器已連線到它。$ 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": {} } ]
在靠近頂部的位置,會列出關於
bridge
網路的資訊,包括 Docker 主機和bridge
網路之間閘道的 IP 位址(172.17.0.1
)。在Containers
索引鍵下,會列出每個已連線的容器,以及其 IP 位址的相關資訊(alpine1
為172.17.0.2
,alpine2
為172.17.0.3
)。容器正在背景中執行。使用
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
顯示的位址相同。從
alpine1
內部,透過 pinggoogle.com
確保您可以連線到網際網路。-c 2
旗標將命令限制為兩次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
現在嘗試 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'
使用分離序列
CTRL
+p
CTRL
+q
(按住CTRL
並輸入p
,然後輸入q
)從alpine1
分離,而不停止它。如果您願意,可以附加到alpine2
並在那裡重複步驟 4、5 和 6,將alpine1
替換為alpine2
。停止並移除兩個容器。
$ docker container stop alpine1 alpine2 $ docker container rm alpine1 alpine2
請記住,不建議將預設的 bridge
網路用於生產環境。若要了解使用者定義的橋接網路,請繼續閱讀下一個教學課程。
使用使用者定義的橋接網路
在此範例中,我們再次啟動兩個 alpine
容器,但將它們連接到一個我們已建立的名為 alpine-net
的使用者自訂網路。這些容器根本沒有連接到預設的 bridge
網路。然後,我們啟動第三個 alpine
容器,它連接到 bridge
網路,但沒有連接到 alpine-net
,以及第四個 alpine
容器,它連接到這兩個網路。
建立
alpine-net
網路。由於--driver bridge
標誌是預設值,因此您不需要它,但此範例顯示了如何指定它。$ docker network create --driver bridge alpine-net
列出 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 位址在您的系統上可能不同。建立您的四個容器。請注意
--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 alpine1
再次檢查
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": {} } ]
容器
alpine3
和alpine4
連接到bridge
網路。$ 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
網路。在像
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
。回顧bridge
網路的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
使用 detach 序列
CTRL
+p
CTRL
+q
(按住CTRL
並鍵入p
,然後鍵入q
)從alpine1
detach。請記住,
alpine4
連接到預設的bridge
網路和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
作為最後的測試,請透過 ping
google.com
確保您的容器都可以連接到網際網路。您已經連接到alpine4
,因此請先從那裡嘗試。接下來,從alpine4
detach 並連接到alpine3
(它僅連接到bridge
網路)並再次嘗試。最後,連接到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
停止並移除所有容器和
alpine-net
網路。$ docker container stop alpine1 alpine2 alpine3 alpine4 $ docker container rm alpine1 alpine2 alpine3 alpine4 $ docker network rm alpine-net