Docker用户指南(10) – Docker容器网络

本文对Docker提供的几个默认网络的行为做个简单介绍。描述默认创建的网络类型,以及如何创建自己的用户定义的网络。同时说明在单台主机或跨主机集群创建网络所需的资源。

默认网络

当你安装Docker后,它自动创建了三个网络。你可以使用docker network ls命令来列出这些网络。

  1. $ docker network ls
  2.  
  3. NETWORK ID          NAME                DRIVER
  4. 7fca4eb8c647        bridge              bridge
  5. 9f904ee27bf5        none                null
  6. cf03ee007fb4        host                host

历史上,这三个网络是Docker的一部分。当你运行一个容器时,你可以使用–network参数来指定你想运行容器在哪个网络上。这三个网络仍然可用。
称为docker0的bridge网络出现在所有Docker的安装中。除非你使用docker run –network=来指定其它网络,否则Docker daemon默认连接容器到这个网络。你可以在主机使用ifconfig命令看到这个bridge是主机网络堆栈的一部分。

  1. $ ifconfig
  2.  
  3. docker0   Link encap:Ethernet  HWaddr 02:42:47:bc:3a:eb
  4.           inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
  5.           inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link
  6.           UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
  7.           RX packets:17 errors:0 dropped:0 overruns:0 frame:0
  8.           TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
  9.           collisions:0 txqueuelen:0
  10.           RX bytes:1100 (1.1 KB)  TX bytes:648 (648.0 B)

none网络添加一个容器到一个容器特定网络堆栈。这样会使那个容器缺少网络接口。附加到这样一个容器,按如下来查看:

  1. $ docker attach nonenetcontainer
  2.  
  3. root@0cb243cd1293:/# cat /etc/hosts
  4. 127.0.0.1   localhost
  5. ::1 localhost ip6-localhost ip6-loopback
  6. fe00::0 ip6-localnet
  7. ff00::0 ip6-mcastprefix
  8. ff02::1 ip6-allnodes
  9. ff02::2 ip6-allrouters
  10. root@0cb243cd1293:/# ifconfig
  11. lo        Link encap:Local Loopback
  12.           inet addr:127.0.0.1  Mask:255.0.0.0
  13.           inet6 addr: ::1/128 Scope:Host
  14.           UP LOOPBACK RUNNING  MTU:65536  Metric:1
  15.           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  16.           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
  17.           collisions:0 txqueuelen:0
  18.           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
  19.  
  20. root@0cb243cd1293:/#

注意:你按下CTRL-p CTRL-q与容器分离。

host网络添加一个容器到主机的网络堆栈。你会发现容器内的网络配置与主机的相同。
除了bridge网络,你不需要与这些默认的网络交互。虽然你能列出和查看它们,你不能删除它们。因为Docker的安装依赖它们。不过你可以添加你自己自定义的网络并且不再需要它们时可以删除。在学习创建你自己的网络之前,值得再看下默认的bridge网络。

默认的bridge网络详细信息

默认的bridge网络存在于所有的Docker主机中。docker network inspect网络返回关于网络的信息:

  1. $ docker network inspect bridge
  2.  
  3. [
  4.    {
  5.        "Name": "bridge",
  6.        "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
  7.        "Scope": "local",
  8.        "Driver": "bridge",
  9.        "IPAM": {
  10.            "Driver": "default",
  11.            "Config": [
  12.                {
  13.                    "Subnet": "172.17.0.1/16",
  14.                    "Gateway": "172.17.0.1"
  15.                }
  16.            ]
  17.        },
  18.        "Containers": {},
  19.        "Options": {
  20.            "com.docker.network.bridge.default_bridge": "true",
  21.            "com.docker.network.bridge.enable_icc": "true",
  22.            "com.docker.network.bridge.enable_ip_masquerade": "true",
  23.            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
  24.            "com.docker.network.bridge.name": "docker0",
  25.            "com.docker.network.driver.mtu": "9001"
  26.        }
  27.    }
  28. ]

Docker Engine自动给这个网络创建一个子网和网关。docker run命令自动地增加新容器到这个网络。

  1. $ docker run -itd --name=container1 busybox
  2.  
  3. 3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c
  4.  
  5. $ docker run -itd --name=container2 busybox
  6.  
  7. 94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c

启动这两个容器后重新查看bridge网络会看到在这个网络有两个新启动的容器。它们的id显示在docker network inspect命令输出的“Containers”区块中:

  1. $ docker network inspect bridge
  2.  
  3. {[
  4.     {
  5.         "Name": "bridge",
  6.         "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
  7.         "Scope": "local",
  8.         "Driver": "bridge",
  9.         "IPAM": {
  10.             "Driver": "default",
  11.             "Config": [
  12.                 {
  13.                     "Subnet": "172.17.0.1/16",
  14.                     "Gateway": "172.17.0.1"
  15.                 }
  16.             ]
  17.         },
  18.         "Containers": {
  19.             "3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c": {
  20.                 "EndpointID": "647c12443e91faf0fd508b6edfe59c30b642abb60dfab890b4bdccee38750bc1",
  21.                 "MacAddress": "02:42:ac:11:00:02",
  22.                 "IPv4Address": "172.17.0.2/16",
  23.                 "IPv6Address": ""
  24.             },
  25.             "94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c": {
  26.                 "EndpointID": "b047d090f446ac49747d3c37d63e4307be745876db7f0ceef7b311cbba615f48",
  27.                 "MacAddress": "02:42:ac:11:00:03",
  28.                 "IPv4Address": "172.17.0.3/16",
  29.                 "IPv6Address": ""
  30.             }
  31.         },
  32.         "Options": {
  33.             "com.docker.network.bridge.default_bridge": "true",
  34.             "com.docker.network.bridge.enable_icc": "true",
  35.             "com.docker.network.bridge.enable_ip_masquerade": "true",
  36.             "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
  37.             "com.docker.network.bridge.name": "docker0",
  38.             "com.docker.network.driver.mtu": "9001"
  39.         }
  40.     }
  41. ]

上面的docker network inspect命令显示所有连接的容器和它们的网络资源。在这个默认网络的容器能够使用IP地址来互相通信。在这个默认的bridge网络Docker不支持自动服务发现。如果你想在这个默认的bridge网络使用容器名称来通信,你必须通过旧的docker run –link选项来连接容器。
你可以attach一个运行中的容器来查看它的配置:

  1. $ docker attach container1
  2.  
  3. root@0cb243cd1293:/# ifconfig
  4. eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02
  5.           inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
  6.           inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
  7.           UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
  8.           RX packets:16 errors:0 dropped:0 overruns:0 frame:0
  9.           TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
  10.           collisions:0 txqueuelen:0
  11.           RX bytes:1296 (1.2 KiB)  TX bytes:648 (648.0 B)
  12.  
  13. lo        Link encap:Local Loopback
  14.           inet addr:127.0.0.1  Mask:255.0.0.0
  15.           inet6 addr: ::1/128 Scope:Host
  16.           UP LOOPBACK RUNNING  MTU:65536  Metric:1
  17.           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  18.           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
  19.           collisions:0 txqueuelen:0
  20.           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

然后使用ping来发送三个ICMP请求测试在bridge网络的容器之间的连接性。

  1. root@0cb243cd1293:/# ping -w3 172.17.0.3
  2.  
  3. PING 172.17.0.3 (172.17.0.3): 56 data bytes
  4. 64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.096 ms
  5. 64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.080 ms
  6. 64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.074 ms
  7.  
  8. --- 172.17.0.3 ping statistics ---
  9. 3 packets transmitted, 3 packets received, 0% packet loss
  10. round-trip min/avg/max = 0.074/0.083/0.096 ms

最后,使用cat命令检查container1网络配置:

  1. root@0cb243cd1293:/# cat /etc/hosts
  2.  
  3. 172.17.0.2  3386a527aa08
  4. 127.0.0.1   localhost
  5. ::1 localhost ip6-localhost ip6-loopback
  6. fe00::0 ip6-localnet
  7. ff00::0 ip6-mcastprefix
  8. ff02::1 ip6-allnodes
  9. ff02::2 ip6-allrouters

按下CTRL-p CTRL-q离开container1,再attach到container2和重复这三个命令。

  1. $ docker attach container2
  2.  
  3. root@0cb243cd1293:/# ifconfig
  4. eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:03
  5.           inet addr:172.17.0.3  Bcast:0.0.0.0  Mask:255.255.0.0
  6.           inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link
  7.           UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
  8.           RX packets:15 errors:0 dropped:0 overruns:0 frame:0
  9.           TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
  10.           collisions:0 txqueuelen:0
  11.           RX bytes:1166 (1.1 KiB)  TX bytes:1026 (1.0 KiB)
  12.  
  13. lo        Link encap:Local Loopback
  14.           inet addr:127.0.0.1  Mask:255.0.0.0
  15.           inet6 addr: ::1/128 Scope:Host
  16.           UP LOOPBACK RUNNING  MTU:65536  Metric:1
  17.           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  18.           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
  19.           collisions:0 txqueuelen:0
  20.           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
  21.  
  22. root@0cb243cd1293:/# ping -w3 172.17.0.2
  23.  
  24. PING 172.17.0.2 (172.17.0.2): 56 data bytes
  25. 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.067 ms
  26. 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms
  27. 64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.072 ms
  28.  
  29. --- 172.17.0.2 ping statistics ---
  30. 3 packets transmitted, 3 packets received, 0% packet loss
  31. round-trip min/avg/max = 0.067/0.071/0.075 ms
  32. / # cat /etc/hosts
  33. 172.17.0.3  94447ca47985
  34. 127.0.0.1   localhost
  35. ::1 localhost ip6-localhost ip6-loopback
  36. fe00::0 ip6-localnet
  37. ff00::0 ip6-mcastprefix
  38. ff02::1 ip6-allnodes
  39. ff02::2 ip6-allrouters

默认的docker0 bridge网络支持端口映射的使用,docker run –link允许在docker0网络中的容器之间通信。这些技术设置起来很麻烦,容易出错。不过它们仍然可用,最后定义自己的bridge网络来避免它们。

自定义网络

你可以创建自己定义的网络来更好的隔离容器。Docker为方便创建这些网络提供了一些默认的网络驱动。你可以创建一个bridge网络,overlay网络或MACVLAN网络。你也可以创建一个写入自己规格的网络插件(network plugin)或远程网络(remote network)。
你既能创建多个网络,也能添加容器到多个网络。容器只能在它加入的网络内通信不过跨网络。一个容器附加到两个网络能与这两个网络的所有成员通信。当一个容器连接多个网络时,由第一个非内部网络提供外部连接。

bridge网络

创建最简单的自定义网络是bridge网络。这个网络类似于历史默认的docker0网络。不过增加了一些新的功能和一些旧的功能不再可用。

  1. $ docker network create --driver bridge isolated_nw
  2. 1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b
  3.  
  4. $ docker network inspect isolated_nw
  5.  
  6. [
  7.     {
  8.         "Name": "isolated_nw",
  9.         "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
  10.         "Scope": "local",
  11.         "Driver": "bridge",
  12.         "IPAM": {
  13.             "Driver": "default",
  14.             "Config": [
  15.                 {
  16.                     "Subnet": "172.21.0.0/16",
  17.                     "Gateway": "172.21.0.1/16"
  18.                 }
  19.             ]
  20.         },
  21.         "Containers": {},
  22.         "Options": {}
  23.     }
  24. ]
  25.  
  26. $ docker network ls
  27.  
  28. NETWORK ID          NAME                DRIVER
  29. 9f904ee27bf5        none                null
  30. cf03ee007fb4        host                host
  31. 7fca4eb8c647        bridge              bridge
  32. c5ee82f76de3        isolated_nw         bridge

创建网络后,你可以使用docker run –network=选项来加入这个网络。

  1. $ docker run --network=isolated_nw -itd --name=container3 busybox
  2.  
  3. 8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c
  4.  
  5. $ docker network inspect isolated_nw
  6. [
  7.     {
  8.         "Name": "isolated_nw",
  9.         "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
  10.         "Scope": "local",
  11.         "Driver": "bridge",
  12.         "IPAM": {
  13.             "Driver": "default",
  14.             "Config": [
  15.                 {}
  16.             ]
  17.         },
  18.         "Containers": {
  19.             "8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c": {
  20.                 "EndpointID": "93b2db4a9b9a997beb912d28bcfc117f7b0eb924ff91d48cfa251d473e6a9b08",
  21.                 "MacAddress": "02:42:ac:15:00:02",
  22.                 "IPv4Address": "172.21.0.2/16",
  23.                 "IPv6Address": ""
  24.             }
  25.         },
  26.         "Options": {}
  27.     }
  28. ]

你要加入到这个网络的容器必须在同一台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网络。

    1. $ docker network create --subnet 172.30.0.0/16 \
    2.                         --opt com.docker.network.bridge.name=docker_gwbridge \
    3.             --opt com.docker.network.bridge.enable_icc=false \
    4.             docker_gwbridge

    当你使用overlay网络时docker_gwbridge始终存在。

    Docker Engine swarm模式的overylay网络

    你可以在运行着swarm模式的管理节点上创建一个不需要外部键值存储的overylay网络。overlay网络只可用于服务依赖它的swarm节点上。当你创建一个服务使用overlay网络时,管理节点自动扩展overlay网络到运行服务任务的节点上。
    下面的示例显示如何创建一个网络并设置一个服务使用这个网络:

    1. # Create an overlay network `my-multi-host-network`.
    2. $ docker network create \
    3.   --driver overlay \
    4.   --subnet 10.0.9.0/24 \
    5.   my-multi-host-network
    6.  
    7. 400g6bwzd68jizzdx5pgyoe95
    8.  
    9. # Create an nginx service and extend the my-multi-host-network to nodes where
    10. # the service's tasks run.
    11. $ docker service create --replicas 2 --network my-multi-host-network --name my-web nginx
    12.  
    13. 716thylsndqma81j6kkkb5aus

    依赖外部键值存储的overlay网络

    如果你的Docker Engine没有运行在swarm模式中,overlay网络则需要一个有效的键值存储服务。支持键值存储包括Consul, Etcd和ZooKeeper(分布式存储)。在这个Engine版本创建这个网络前,你必须安装和配置一个键值存储服务。要加入到这个网络的docker主机和服务必须能与这个键值存储服务通信。

    注意:运行在swarm模式的docker engine与使用一个外部键值存储的网络不兼容。


    在这个网络的每一个主机必须运行一个docker engine实例。

    在每一个主机之间需要开放如下端口。

    协议 端口 描述
    udp 4789 Data plane (VXLAN)
    tcp/udp 7946 Control plane

    要创建一个overlay网络,还需要在每个主机的docker daemon配置如下选项:

    选项 描述
    –cluster-store=PROVIDER://URL 键值服务地址
    –cluster-advertise=HOST_IP|HOST_IFACE:PORT 用于集群的IP地址,接口和端口
    –cluster-store-opt=KEY-VALUE OPTIONS TLS证书或调整发现时间等选项

    在集群中一个机器上创建一个overlay网络。

    1. $ docker network create --driver overlay my-multi-host-network

    这使得一个网络可以跨越多个主机。overlay网络为容器提供完全的隔离。

    然后,在每个主机上运行容器时确保指定网络名称。

    1. $ docker run -itd --network=my-multi-host-network busybox

    一旦容器连接到这个网络,每个容器就有权限访问这个网络中的所有容器,不管容器是在哪个主机运行的。

    自定义网络插件

    如果你想,你如果编写自己的网络驱动插件。网络驱动插件使用Docker的插件基础设施。在这个基础设施中,插件是在与Docker守护程序相同的Docker主机上运行的进程。网络插件遵循与其他插件相同的限制和安装规则。所有插件都使用插件API。它们具有包括安装,启动,停止和激活的生命周期。一旦创建并安装了自定义网络驱动程序,就可以像内置网络驱动一样使用它。 例如:

    1. $ docker network create --driver weave mynet

    你可以查看这个自定义网络,添加容器到这个网络等等。

    Docker内置的DNS服务器

    Docker daemon运行一个内置的DNS服务器为连接到自定义网络的容器提供自动服务发现功能。从容器发来的域名解析请求首先由内置的DNS服务器处理。如果内置的DNS服务器无法解析这个请求,那么它就将此请求转发到容器配置的外部DNS服务器。

    标签:Docker容器 发布于:2019-11-20 02:57:53