Networking with standalone containers
这个系列的教程是关于如何处理standalone Docker containers网络。如果想了解swarm service相关网络,请参阅 Networking with swarm services。如果需要对Docker的网络了解更多,请参阅overview](docs.docker.com/network/)。
本章节包含三个不同的教程。你可以在Linux,Windows或Mac上运行任何一个,但对于后两者,你需要在别处运行第二个Docker host。
- 使用默认的bridge network解释了如何使用默认的
bridge网络,它由Docker自动创建,但对生产环境来说,它并不是一个很好的选择。 - 使用用户定义的bridge network展示了如何创建并使用你自定义的bridge network,将运行在同一Docker host上的container连接起来。
尽管overlay networks 通常是用在swarm services上的,你也可以在standalone container上使用。可参阅tutorial on using overlay networks.
Use the default bridge network
在本例中,你将在同一Docker host上启动两个不同的alpine容器,并做一些tests来理解他们是如何互相交流的。
-
打开一个terminal window。将当前所有的networks 列出来。如果你没有在该Docker daemon上添加过network或初始化过swarm services。你至少会看到以下networks:
docker network ls NETWORK ID NAME DRIVER SCOPE 17e324f45964 bridge bridge local 6ed54d316334 host host local 7092879f2cc8 none null local有默认的
bridge以及host和none。后两种可用于让容器直接连接到Docker daemon主机的网络或者让容器不连接任何网络。本教程会将两个container用bridgenetwork连接。 -
启动两个运行着
ash的alpine容器,ash是alpine的默认的shell而非bash。-dit意味着detached,interactive和TTY,detached即以分离的方式运行容器(即后台),interactive即可以进行输入,TTY意味着你可以看见输入和输出。由于你是以分离的方式启动的容器,你不会立即连接到容器,而是只打印出容器的id。由于你没有指定--network,容器会连接到默认的bridgenetwork。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 -
检查
bridgenetwork来查看有哪些容器连接到该network。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": {} } ]在最上方,列出 了关于
bridgenetwork的相关信息,包括介于Docker host和bridgenetwork的Gateway的IP地址:172.17.0.1。在Containers属性下,列出了每个连接到该网络的container以及其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第一个接口是loopback 设备,先暂时忽略它。请注意第二个接口的IP为
172.17.0.2,这与先前所展示ip地址相同。 -
通过ping
google.com来确认你可以连接到网络上。-c 2将命令限制为两次尝试。# 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第二个容器,首先,ping它的ip地址
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 容器名的方式
# ping -c 2 alpine2 ping: bad address 'alpine2' -
要想从
alpone1中退出并且不停止该容器的方法是使用detach sequence,CTRL + p CTRL+q(按住ctrl再按p再按q)。 -
停止并删除这两个容器
docker container stop alpine1 alpine2 docker container rm alpine1 alpine2
请注意,默认的bridge network不推荐在生产环境中使用。下面的教程会介绍用户自定义的bridge network。
Use user-defined bridge networks
在本示例中,我们再次启动两个alpine容器,但是将它们连接到用户自定义的network(alpine-net)上。这些container不会连接到默认的bridge network。然后再创建第三个aphine container,使它连接到bridge network但不连接到alpine-net,创建第四个alpinecontainer,使其与这两个网络都连接。
-
创建
alpine-netnetwork。你不需要添加--driver bridge,因为它是默认的,这里只是为了展示如何指定driverdocker network create --driver bridge alpine-net -
将Docker的network列出来
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-netnetwork,展示了其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": {} } ]请注意这个network的gateway是
172.18.0.1,默认的bridge network是172.17.0.1。 -
下面开始创建这4个容器。请注意
--network,你在docker run命令中只能连接到一个network,所以你需要再使用docker network将alpine4连接到bridgenetwork。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查看正在运行的container
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 -
查看
bridgenetwork和alpine-netnetworkdocker 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": {} } ]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": {} } ] -
我们自定义的network(像
alpine-net),容器不仅通过IP地址进行沟通,还可以将容器的名字解析为一个IP地址。这个能力被称为自动服务发现。让我们连接到alpine1并进行测试。alpine1能够将alpine2和alpine4和其自身解析为IP地址。 Note 自动服务发现只能处理自定义的容器名字,而不能处理自动生成的名字。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-netnetwork上。# ping -c 2 alpine3 ping: bad address 'alpine3'即使访问
alpine3的IP也不行。# 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 -
还记得
alpine4是连接到默认的bridge和alpine-netnetwork上吗?它可以访问所有其他的容器。然而,你要访问alpine3的话只能通过其IP地址。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进行检查。# 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-netnetworkdocker container stop alpine1 alpine2 alpine3 alpine4 docker container rm alpine1 alpine2 alpine3 alpine4 docker network rm alpine-net