Docker用户指南(10) – Docker容器网络
本文对Docker提供的几个默认网络的行为做个简单介绍。描述默认创建的网络类型,以及如何创建自己的用户定义的网络。同时说明在单台主机或跨主机集群创建网络所需的资源。
默认网络
当你安装Docker后,它自动创建了三个网络。你可以使用docker network ls命令来列出这些网络。
$ docker network ls NETWORK ID NAME DRIVER 7fca4eb8c647 bridge bridge 9f904ee27bf5 none null cf03ee007fb4 host host
历史上,这三个网络是Docker的一部分。当你运行一个容器时,你可以使用–network参数来指定你想运行容器在哪个网络上。这三个网络仍然可用。
称为docker0的bridge网络出现在所有Docker的安装中。除非你使用docker run –network=
$ ifconfig docker0 Link encap:Ethernet HWaddr 02:42:47:bc:3a:eb inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1 RX packets:17 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1100 (1.1 KB) TX bytes:648 (648.0 B)
none网络添加一个容器到一个容器特定网络堆栈。这样会使那个容器缺少网络接口。附加到这样一个容器,按如下来查看:
$ docker attach nonenetcontainer root@0cb243cd1293:/# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters root@0cb243cd1293:/# ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) root@0cb243cd1293:/#
注意:你按下CTRL-p CTRL-q与容器分离。
host网络添加一个容器到主机的网络堆栈。你会发现容器内的网络配置与主机的相同。
除了bridge网络,你不需要与这些默认的网络交互。虽然你能列出和查看它们,你不能删除它们。因为Docker的安装依赖它们。不过你可以添加你自己自定义的网络并且不再需要它们时可以删除。在学习创建你自己的网络之前,值得再看下默认的bridge网络。
默认的bridge网络详细信息
默认的bridge网络存在于所有的Docker主机中。docker network inspect网络返回关于网络的信息:
$ docker network inspect bridge [ { "Name": "bridge", "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f", "Scope": "local", "Driver": "bridge", "IPAM": { "Driver": "default", "Config": [ { "Subnet": "172.17.0.1/16", "Gateway": "172.17.0.1" } ] }, "Containers": {}, "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": "9001" } } ]
Docker Engine自动给这个网络创建一个子网和网关。docker run命令自动地增加新容器到这个网络。
$ docker run -itd --name=container1 busybox 3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c $ docker run -itd --name=container2 busybox 94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c
启动这两个容器后重新查看bridge网络会看到在这个网络有两个新启动的容器。它们的id显示在docker network inspect命令输出的“Containers”区块中:
$ docker network inspect bridge {[ { "Name": "bridge", "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f", "Scope": "local", "Driver": "bridge", "IPAM": { "Driver": "default", "Config": [ { "Subnet": "172.17.0.1/16", "Gateway": "172.17.0.1" } ] }, "Containers": { "3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c": { "EndpointID": "647c12443e91faf0fd508b6edfe59c30b642abb60dfab890b4bdccee38750bc1", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" }, "94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c": { "EndpointID": "b047d090f446ac49747d3c37d63e4307be745876db7f0ceef7b311cbba615f48", "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": "9001" } } ]
上面的docker network inspect命令显示所有连接的容器和它们的网络资源。在这个默认网络的容器能够使用IP地址来互相通信。在这个默认的bridge网络Docker不支持自动服务发现。如果你想在这个默认的bridge网络使用容器名称来通信,你必须通过旧的docker run –link选项来连接容器。
你可以attach一个运行中的容器来查看它的配置:
$ docker attach container1 root@0cb243cd1293:/# ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02 inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1 RX packets:16 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1296 (1.2 KiB) TX bytes:648 (648.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
然后使用ping来发送三个ICMP请求测试在bridge网络的容器之间的连接性。
root@0cb243cd1293:/# ping -w3 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.096 ms 64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.080 ms 64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.074 ms --- 172.17.0.3 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 0.074/0.083/0.096 ms
最后,使用cat命令检查container1网络配置:
root@0cb243cd1293:/# cat /etc/hosts 172.17.0.2 3386a527aa08 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters
按下CTRL-p CTRL-q离开container1,再attach到container2和重复这三个命令。
$ docker attach container2 root@0cb243cd1293:/# ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03 inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1 RX packets:15 errors:0 dropped:0 overruns:0 frame:0 TX packets:13 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1166 (1.1 KiB) TX bytes:1026 (1.0 KiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) root@0cb243cd1293:/# ping -w3 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.067 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms 64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.072 ms --- 172.17.0.2 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 0.067/0.071/0.075 ms / # cat /etc/hosts 172.17.0.3 94447ca47985 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters
默认的docker0 bridge网络支持端口映射的使用,docker run –link允许在docker0网络中的容器之间通信。这些技术设置起来很麻烦,容易出错。不过它们仍然可用,最后定义自己的bridge网络来避免它们。
自定义网络
你可以创建自己定义的网络来更好的隔离容器。Docker为方便创建这些网络提供了一些默认的网络驱动。你可以创建一个bridge网络,overlay网络或MACVLAN网络。你也可以创建一个写入自己规格的网络插件(network plugin)或远程网络(remote network)。
你既能创建多个网络,也能添加容器到多个网络。容器只能在它加入的网络内通信不过跨网络。一个容器附加到两个网络能与这两个网络的所有成员通信。当一个容器连接多个网络时,由第一个非内部网络提供外部连接。
bridge网络
创建最简单的自定义网络是bridge网络。这个网络类似于历史默认的docker0网络。不过增加了一些新的功能和一些旧的功能不再可用。
$ docker network create --driver bridge isolated_nw 1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b $ docker network inspect isolated_nw [ { "Name": "isolated_nw", "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b", "Scope": "local", "Driver": "bridge", "IPAM": { "Driver": "default", "Config": [ { "Subnet": "172.21.0.0/16", "Gateway": "172.21.0.1/16" } ] }, "Containers": {}, "Options": {} } ] $ docker network ls NETWORK ID NAME DRIVER 9f904ee27bf5 none null cf03ee007fb4 host host 7fca4eb8c647 bridge bridge c5ee82f76de3 isolated_nw bridge
创建网络后,你可以使用docker run –network=
$ docker run --network=isolated_nw -itd --name=container3 busybox 8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c $ docker network inspect isolated_nw [ { "Name": "isolated_nw", "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b", "Scope": "local", "Driver": "bridge", "IPAM": { "Driver": "default", "Config": [ {} ] }, "Containers": { "8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c": { "EndpointID": "93b2db4a9b9a997beb912d28bcfc117f7b0eb924ff91d48cfa251d473e6a9b08", "MacAddress": "02:42:ac:15:00:02", "IPv4Address": "172.21.0.2/16", "IPv6Address": "" } }, "Options": {} } ]
你要加入到这个网络的容器必须在同一台docker主机上。在这个网络的每一个容器能马上与在这个网络的其它容器通信。虽然网络本身将容器与外部网络隔离了。
在一个自定义的bridge网络中,linking是不支持的。你可以在这个网络的容器公开和发布容器端口。如果你想使bridge的一部分容器可用于一个外部的网络会非常有用。
你想在一个主机运行一个相关的小的网络这种场景下,可以使用bridge网络。
docker_gwbridge网络
在两种不同的情况下docker会自动创建一个本地bridge网络docker_gwbridge:
当你初始化或加入一个swarm,docker创建docker_gwbridge网络并用它来与不同的主机上的swarm节点之间通信。 当没有一个容器网络能提供外部连接时,docker连接容器到docker_gwbridge网络以及容器的其它网络,以使得容器能连接外部网络或其它swarm节点。如果你需要一个自定义的配置你可以提前创建docker_gwbridge网络,否则docker会根据需要创建它。下面的示例使用一些自定义选项来创建docker_gwbridge网络。
$ docker network create --subnet 172.30.0.0/16 --opt com.docker.network.bridge.name=docker_gwbridge --opt com.docker.network.bridge.enable_icc=false docker_gwbridge
当你使用overlay网络时docker_gwbridge始终存在。
Docker Engine swarm模式的overylay网络
你可以在运行着swarm模式的管理节点上创建一个不需要外部键值存储的overylay网络。overlay网络只可用于服务依赖它的swarm节点上。当你创建一个服务使用overlay网络时,管理节点自动扩展overlay网络到运行服务任务的节点上。
下面的示例显示如何创建一个网络并设置一个服务使用这个网络:
# Create an overlay network `my-multi-host-network`. $ docker network create --driver overlay --subnet 10.0.9.0/24 my-multi-host-network 400g6bwzd68jizzdx5pgyoe95 # Create an nginx service and extend the my-multi-host-network to nodes where # the service's tasks run. $ docker service create --replicas 2 --network my-multi-host-network --name my-web nginx 716thylsndqma81j6kkkb5aus
依赖外部键值存储的overlay网络
如果你的Docker Engine没有运行在swarm模式中,overlay网络则需要一个有效的键值存储服务。支持键值存储包括Consul, Etcd和ZooKeeper(分布式存储)。在这个Engine版本创建这个网络前,你必须安装和配置一个键值存储服务。要加入到这个网络的docker主机和服务必须能与这个键值存储服务通信。
注意:运行在swarm模式的docker engine与使用一个外部键值存储的网络不兼容。
在这个网络的每一个主机必须运行一个docker engine实例。
在每一个主机之间需要开放如下端口。
要创建一个overlay网络,还需要在每个主机的docker daemon配置如下选项:
在集群中一个机器上创建一个overlay网络。
$ docker network create --driver overlay my-multi-host-network
这使得一个网络可以跨越多个主机。overlay网络为容器提供完全的隔离。
然后,在每个主机上运行容器时确保指定网络名称。
$ docker run -itd --network=my-multi-host-network busybox
一旦容器连接到这个网络,每个容器就有权限访问这个网络中的所有容器,不管容器是在哪个主机运行的。
自定义网络插件
如果你想,你如果编写自己的网络驱动插件。网络驱动插件使用Docker的插件基础设施。在这个基础设施中,插件是在与Docker守护程序相同的Docker主机上运行的进程。网络插件遵循与其他插件相同的限制和安装规则。所有插件都使用插件API。它们具有包括安装,启动,停止和激活的生命周期。一旦创建并安装了自定义网络驱动程序,就可以像内置网络驱动一样使用它。 例如:
$ docker network create --driver weave mynet
你可以查看这个自定义网络,添加容器到这个网络等等。
Docker内置的DNS服务器
Docker daemon运行一个内置的DNS服务器为连接到自定义网络的容器提供自动服务发现功能。从容器发来的域名解析请求首先由内置的DNS服务器处理。如果内置的DNS服务器无法解析这个请求,那么它就将此请求转发到容器配置的外部DNS服务器。
版权声明:Docker用户指南(10) – Docker容器网络是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。