概述

通常来说,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包,另外,如果不同子网之间要进行通信,还需要路由机制。Docker中的网络接口默认都是虚拟接口,虚拟接口的优势之一是转发效率较高。

Linux通过在内核中进行数据复制来实现虚拟接口之间的数据转发,通俗地讲,发送接口发送缓存数据包被直接复制到接收接口接收缓存中,对于本地系统和容器内系统来说,就像是一个正常的以太网卡,但它不需要真正与外部网络设备通信,因此速度快,转发效率高。

Docker的网络实现其实就是利用了该技术,即利用了Linux上的网络命名空间和虚拟网络设备实现的,特别是veth pair,它在宿主机和容器内分别创建虚拟接口,并让它们彼此连通。

Docker网络实现原理

启动Docker时会在宿主机上创建一个名为docker0的虚拟网桥,Docker启动一个容器时会根据docker0的网段划分容器的虚拟子网和私有IP,容器内的虚拟接口为eth0,各容器的网关则是docker0的IP。

Docker创建一个容器的时候,会执行如下操作:

  1. 创建一对虚拟接口,即veth pair,分别放到宿主机和容器中;
  2. 主机一端桥接到默认的docker0或指定网桥上,具有一个唯一的名字,如veth0ac844e;
  3. 另一端放到新容器中,并修改名字为eth0,该接口只在容器的命名空间可见;
  4. 从网桥可用地址段中获取一个空闲地址分配给容器的eth0,并配置默认路由到桥接网卡veth0ac844e

这样,该容器就可以使用eth0虚拟网卡来连接其它容器和网络了。当该容器结束后,Docker会清空容器,容器内的eth0会随网络命名空间一起被清除,veth0ac844e接口也被自动从docker0卸载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ ip addr # 可以看到网桥docker0分配的子网段是172.17.0.1/16
...
7: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:74:d9:49:de brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:74ff:fed9:49de/64 scope link
valid_lft forever preferred_lft forever
...
$ brctl show # 可以看到网桥docker0上的虚拟接口
bridge name bridge id STP enabled interfaces
docker0 8000.024274d949de no veth0ac844e
veth36e091d
$ brctl showstp docker0 # 查看网桥docker0的生成树状态
...
$ ethtool -i docker0 # 查看网桥docker0的网卡驱动类型
driver: bridge
version: 2.3
...
$ ethtool -S veth0ac844e # 查看该网络接口的唯一识别编号peer_ifindex
NIC statistics:
peer_ifindex: 10
$ ip link # 进入容器后运行该命令,查看veth编号
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
10: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff

Docker容器网络模型

网络模型基本组件

在容器网络模型中,通常会包括容器(Container)、沙箱(Sandbox)、端点(Endpoint)、网络(Network)等组件,其中,网络会涉及桥接网(Bridge Network)或重叠网(Overlay Network)。

容器网络模型示意图如下图所示:

  • 容器(Container): 容器能够作为任意一个或多个网络的一部分,能够同时对接桥接网和重叠网网络。
  • 沙箱(Sandbox): 包含容器网络堆栈配置信息,是一个隔离的环境,可能包含多网络的多个端点。
  • 端点(Endpoint): 连接沙箱和网络的接口,绑定到特定的网络,比如之前提到的veth pair
  • 网络(Network): 使得一组端点之间能够相互直接交流的,实现可以是Linux网桥或重叠网。

容器网络模型优势

首先,与Docker Links进行简单对比,Docker Links允许容器之间互相发现,并使用容器名作为别名进行互相之间的通信,比DNS或服务发现更容易使用,且不用关心端口映射,但Docker Links有一些限制,比如:

  • 只能在同一宿主机内使用,不能跨主机
  • 重新创建容器会移除之前的链接(Links)
  • 被链接的容器必须是一个已经启动的容器

因此,在Docker 1.9版本之后,官方推荐使用Docker网络功能代替Docker Links。Docker容器网络模型的主要优势在于:

  • 在某个特定网络下的所有容器能自由地相互通信
  • 多个网络有助于分散容器之间的流量传输
  • 多个端点允许一个容器加入到多个网络中
  • 能够支持同主机和跨主机的容器间通信

桥接网络与重叠网络

桥接网络(Bridge Network),在同一宿主机上的多个容器可以连接到同一桥接网络来实现彼此网络通信,之前提到了Docker默认的虚拟网桥为docker0,当然也可以创建自定义的网络生成新的虚拟网桥,而将容器连接到的该虚拟网桥上形成的网络称为桥接网络。在运行容器时可指定--net=bridge使用桥接模式,将容器桥接到宿主机的虚拟网桥上,从虚拟网桥的空闲网段中划分出一个子网私有IP分配给该容器。

重叠网络(Overly Network,也有的译成叠加或覆盖网络),在物理网络之上,通过软件定义网络(Software Defined Network, SDN) 创建虚拟网络抽象,使得应用之间在逻辑上彼此隔离,但共享相同的底层物理网络,同时简化网络管理。

Overlay networking is a method of using software to create layers of network abstraction that can be used to run multiple separate, discrete virtualized network layers on top of the physical network, often providing new applications or security benefits.

图片来自网络

更通俗地讲,重叠网是一种运行于一个或多个已存在的网络之上的虚拟网络,即在IPv4底层网络的基础上通过节点之间单播机制将主机两两相连,形成一个虚拟、独立的具有星形和环形拓扑的虚拟网络,就好像在原有的网络上叠加了一层新的网络,以提供特定的附加功能。

重叠网技术的基本思路是在互联网承载层和应用层之间增加一个中间层,结合IP承载网技术,为上层业务和应用提供有针对性的服务,对已有的应用和业务进行适当控制,是对现有互联网体系架构的系统性修补。在软件定义网络领域中,重叠网络的实现大多采用隧道(Tunneling)技术实现,它可以基于现行的IP网络进行叠加部署,消除传统二层网络的限制,如VXLANNVGRE等,都是基于隧道原理实现网络通信,利用叠加在三层网络之上的虚拟网络传递二层数据包,实现了可以跨越三层物理网络进行通信的二层逻辑网络,突破了传统二层网络中存在的物理位置受限、VLAN数量有限等障碍,大幅度降低管理成本和运营风险。

在Docker 1.9之后的版本中,Docker官方集成了重叠网络的特性支持,用户可以在Swarm中使用它或者将其作为Compose工具。通过创建虚拟网络并将其连接到容器上,可实现多个主机上容器相互通信,并且能够实现不同的应用程序或者应用程序不同部分的相互隔离。而在之前的版本中,要实现跨主机的容器间网络通信,需要借助第三方网络插件的实现,可以在后面的章节中了解更多。

Docker四种网络方式

可以在docker run时通过--net参数来指定容器的网络配置,有4种可选值:bridge, host, container:NAME_or_ID, none

bridge模式

使用--net=bridge指定,为默认模式,连接到默认的网桥docker0,此模式会为每个容器分配一个独立的网络命名空间,使用该设置可以看到在容器中创建了eth0
详细举个例子,假如需要创建自定义的网络,命名为web,系统会为其分配一个以br-开头的网桥名,如br-2e9f4f21f001,当指定--net=web时,即连接到对应的网桥上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
$ docker network create web # 默认参数-d, --driver=bridge
2e9f4f21f001fb679b657a9ef020efdd3843d51f7af24a2438114dbcfdd8fce8
$ docker network ls # NAME列即为--net参数可选值,DRIVER列为网卡驱动类型
NETWORK ID NAME DRIVER
100cae621cad bridge bridge
2e9f4f21f001 web bridge
a14b172c4c88 none null
314ed40a56b6 host host
$ ip addr # 为网桥br-2e9f4f21f001分配的子网段是172.18.0.1/16
...
17: br-2e9f4f21f001: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:72:60:5c:14 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 scope global br-2e9f4f21f001
valid_lft forever preferred_lft forever
inet6 fe80::42:72ff:fe60:5c14/64 scope link
valid_lft forever preferred_lft forever
...
$ ethtool -i br-2e9f4f21f001 # 查看网桥br-2e9f4f21f001的网卡驱动类型
driver: bridge
version: 2.3
...
$ modinfo bridge # 查看网卡驱动bridge的详细信息
filename: /lib/modules/3.19.0-32-generic/kernel/net/bridge/bridge.ko
version: 2.3
...
$ docker run -itd --net=web --name web_container busybox
16835c9b647f4e40fb35bfc406e7676280a997d540be2e4a2af5ee6b32a1a10a
$ brctl show # 运行容器后可看到已动态创建并关联了接口veth52ab366
bridge name bridge id STP enabled interfaces
br-2e9f4f21f001 8000.024272605c14 no veth52ab366
...
$ brctl showstp br-2e9f4f21f001 # 也可进一步查看该网桥的生成树状态
...
$ docker network inspect web # 可以看到刚创建的容器已关联并分配了IP
[
{
"Name": "web",
"Id": "2e9f4f21f001fb679b657a9ef020efdd3843d51f7af24a2438114dbcfdd8fce8",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [{}]
},
"Containers": {
"16835c9b647f4e40fb35bfc406e7676280a997d540be2e4a2af5ee6b32a1a10a": {
"EndpointID": "878bd0f230a44d5bcddc08f04a659118005cca25e629049f10a87174175ffeb1",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {}
}
]
$ docker inspect 16835c9b647f # 可进一步查看容器web_container更底层的详细信息
...

host模式

使用--net=host指定,Docker使用的网络和宿主机的一样,该方式创建出来的容器,可以看到主机上所有的网络设备,容器中对这些设备有全部的访问权限。
容器进程可以与主机其它root进程一样,能打开低范围的端口,可以访问本地网络服务,如 D-Bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。
因此,使用这个选项的时候要非常小心,在非隔离的环境中使用host模式是不安全的,如果进一步的使用--privileged=true,容器可以直接配置主机的网络堆栈。

container模式

使用--net=container:CONTAINER_ID/CONTAINER_NAME指定,多个容器使用共同的网络,即两者的网络完全相同。
将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享IP地址和端口等网络资源,两者进程可以直接通过 环回接口 通信。

none模式

使用--net=none指定,这种模式下,将新容器放到隔离的网络栈中,但是不进行网络配置,实际上 nova-docker 用的就是这种方式,这种方式将网络配置的责任完全交给用户,可以实现更加灵活复杂的网络。

Docker网络端口映射

通常来说,容器是用来服务的,这就需要让外部网络能够访问容器,默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。虽然容器本身是有IP地址和端口,但非本地主机是访问不到的,另外,这些IP在容器每次启动时都可能会改变。

Docker给容器内部服务的访问提供了一个简单而可靠的方法,即通过端口绑定主机系统的接口,允许非本地客户端访问容器内部运行的服务,映射容器端口到宿主机的原理是通过在本地的iptables的NAT表中添加相应的规则实现的,可以通过命令sudo iptables -t nat -nL查看,具体可以参阅 端口映射实现 了解更多细节。

自动映射端口

使用-P参数(大写),Docker会自动绑定所有对外提供服务的容器端口,映射的主机端口将会从没有使用的端口池中自动选择。

1
2
3
4
$ docker run -d -P --name review registry:5000/review
$ docker ps -l
CONTAINER ID ... PORTS NAMES
049e50062368 ... 0.0.0.0:32774->8082/tcp review

若指定--expose选项,表示指定需要对外提供服务的端口。

1
2
3
4
$ docker run -d -P --expose 22 --name server ubuntu:14.04
$ docker ps -l
CONTAINER ID ... PORTS NAMES
9a5964ec55d0 ... 0.0.0.0:32779->22/tcp server

指定映射端口

使用-p参数(小写),可以指定要映射的端口,但需要注意的是,在端口映射时应避免主机端口冲突,比如主机的8080端口已经被占用了,那么再映射到该端口就会冲突,即在一个指定端口上只可以绑定一个容器。支持的格式有:

  • [HOST_PORT:]CONTAINER_PORT
    映射所有接口地址,可以指定单组端口映射,比如-p 5678:8082,也可以指定端口映射范围,比如-p 5678-5679:8082-8083,主机的端口范围和容器的端口范围必须有效。

    1
    2
    3
    $ docker run -d -p 8082 --name review_0 registry:5000/review
    $ docker run -d -p 8082:8082 --name review_1 registry:5000/review
    $ docker run -d -p 8182-8183:8082-8083 --name review_2 registry:5000/review

    此时,默认会绑定本地所有接口上的所有地址,即监听所有网络接口。另外,-p可以多次使用来绑定多个端口:

    1
    $ docker run -d -p 8382:8082 -p 8383:8083 --name review registry:5000/review
  • IP:HOST_PORT:CONTAINER_PORT
    映射到指定地址的指定端口,比如这里指定映射使用一个特定地址为localhost地址127.0.0.1

    1
    $ docker run -d -p 127.0.0.1:8282:8082 --name review_3 registry:5000/review
  • IP::CONTAINER_PORT
    映射到指定地址的任意端口,比如这里绑定localhost的任意端口到容器的8082端口,本地主机会自动分配一个端口。

    1
    $ docker run -d -p 127.0.0.1::8082 --name rewew_4 registry:5000/review

    还可以使用udp标记来指定udp端口:

    1
    $ docker run -d -p 127.0.0.1::8082/udp --name review_5 registry:5000/review

查看端口配置

可以通过docker psdocker inspect <CONTAINER>docker port <CONTAINER> [PORT]查看具体的绑定端口和IP等信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ docker port review_2 # 格式为 [container_port] -> [host_ip]:[host_port]
8082/tcp -> 0.0.0.0:8182
8083/tcp -> 0.0.0.0:8183
$ docker port review_2 8082
0.0.0.0:8182
$ docker inspect --format {{.NetworkSettings.IPAddress}} review_2
172.17.0.7
$ ping 172.17.0.7 -c 3
PING 172.17.0.7 (172.17.0.7) 56(84) bytes of data.
64 bytes from 172.17.0.7: icmp_seq=1 ttl=64 time=0.045 ms
...

其中,映射的0.0.0.0表示将接受主机来自所有接口的流量,同时,可通过上节中提到的参数指定允许访问容器的主机上的IP、端口等,以制定更严格的规则。如果希望永久绑定到某个固定的IP地址,可以在Docker配置文件/etc/default/docker中指定DOCKER_OPTS="--ip=IP_ADDRESS",之后重启Docker服务即可生效。

Docker软件定义网络

什么是软件定义网络?

软件定义网络(Software-Defined Networking, SDN),是由 Emulex 提出的一种新型网络创新架构,其核心技术 OpenFlow 协议通过将网络设备控制平面与数据平面分离开来,从而实现了网络流量的灵活控制,为核心网络及应用的创新提供了良好的平台。

The physical separation of the network control plane from the forwarding plane, and where a control plane controls several devices.
SDN is an emerging architecture that is dynamic, manageable, cost-effective, and adaptable, making it ideal for the high-bandwidth, dynamic nature of today’s applications.

图片来自网络

由于传统的网络设备(交换机、路由器)的固件是由设备制造商锁定和控制,而SDN将网络控制与物理网络拓扑分离,创建虚拟网络抽象,从而摆脱硬件对网络架构的限制,并且可对网络架构进行修改。更通俗地讲,网络管理者不直接操作底层的设备,而是通过编程的方式,通过控制器的程序去操作交换机等设备,比如设计转发和路由规则、设计新的网络协议、提供各种各样的服务、实现多个安全方案等,这样的好处在于,可以极大地增强控制层的灵活性。

在DOCKER 1.9之后支持了软件定义网络,增强了网络特性,允许Docker引擎创建虚拟网络,这样,具备网络功能的容器可跨越多个主机进行通信,并且容器间可无缝交流有助于实现真正的分布式应用,另外,开发者也可以更加灵活地搭建类产品环境的测试环境了。

Docker网基本络命令

Docker的network命令主要包含create, connect, disconnect, inspect, ls, prune以及rm,可以通过输入帮助命令查看并了解更多。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ docker network --help
Usage: docker network [OPTIONS] COMMAND [OPTIONS]
Commands:
create Create a network
connect Connect container to a network
disconnect Disconnect container from a network
inspect Display detailed network information
ls List all networks
prune Remove all unused networks
rm Remove a network
Run 'docker network COMMAND --help' for more information on a command.

  • create用法: docker network create [OPTIONS] NETWORK,创建一个新的网络,可配置一些可选参数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    --attachable Enable manual container attachment
    --aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
    -d, --driver string Driver to manage the Network (default "bridge")
    --gateway stringSlice IPv4 or IPv6 Gateway for the master subnet
    --internal Restrict external access to the network
    --ip-range stringSlice Allocate container ip from a sub-range
    --ipam-driver string IP Address Management Driver (default "default")
    --ipam-opt map Set IPAM driver specific options (default map[])
    --ipv6 Enable IPv6 networking
    --label list Set metadata on a network (default [])
    -o, --opt map Set driver specific options (default map[])
    --subnet stringSlice Subnet in CIDR format that represents a network segment

    在创建一个网络时,不指定--driver情况下默认会使用网络驱动bridge,同时创建一个br-开头的虚拟网桥,可以在『Docker四种网络方式』章节的『bridge模式』部分中找到相关命令查看详细信息。另外,驱动hostnull都只能允许管理唯一一个实例网络.

  • connect用法: docker network connect [OPTIONS] NETWORK CONTAINER,连接容器到某个网络中,可选参数:

    1
    2
    3
    4
    5
    --alias stringSlice Add network-scoped alias for the container
    --ip string IP Address
    --ip6 string IPv6 Address
    --link list Add link to another container (default [])
    --link-local-ip stringSlice Add a link-local address for the container
  • disconnect用法: docker network disconnect [OPTIONS] NETWORK CONTAINER,断开容器到网络的连接,可选参数:

    1
    -f, --force Force the container to disconnect from a network
  • inspect用法: docker network inspect [OPTIONS] NETWORK [NETWORK...],显示在某个网络上的详细信息,可选参数:

    1
    -f, --format string Format the output using the given Go template
  • ls用法: docker network ls [OPTIONS],列出当前所有的网络,可选参数:

    1
    2
    3
    4
    -f, --filter filter Provide filter values (e.g. 'driver=bridge')
    --format string Pretty-print networks using a Go template
    --no-trunc Do not truncate the output
    -q, --quiet Only display network IDs
  • prune用法: docker network prune [OPTIONS],删除所有当前未使用的网络,可选参数:

    1
    -f, --force Do not prompt for confirmation
  • rm用法: docker network rm NETWORK [NETWORK...],删除指定的一个或多个网络。

同主机的容器网络通信

通过学习了Docker的网络命令,那接下来就练习一下,在同一主机上准备创建两个网络,分别为webapp,然后分别在其中创建容器,实现web网络下的容器与app网络下的容器相互通信,从而可通过创建虚拟网络模拟出类似产品环境的网络情况。若之前已创建了同名的网络,可根据情况变更网络名称或删除。

创建网络web并运行容器
  • 创建网络web并查看当前所有网络

    1
    2
    $ docker network create web
    $ docker network ls
  • 在网络web下创建名为web_container的容器

    1
    $ docker run -itd --net=web --name web_container busybox
  • 查看网络web下的所有容器

    1
    $ docker network inspect web
创建网络app并运行容器
  • 创建网络app并查看当前所有网络

    1
    2
    $ docker network create app
    $ docker network ls
  • 在网络app下创建名为app_container的容器

    1
    $ docker run -itd --name app_container --net=app busybox
  • 查看网络app下的所有容器

    1
    $ docker network inspect app
连接容器到网络并测试
  • 通过命令实现容器web_container连接到网络app

    1
    $ docker network connect app web_container

    这样,容器web_container就可以通过app_container.app连接到容器app_container

  • 在容器web_container中Ping一下app_container.app

    1
    2
    3
    4
    5
    6
    7
    8
    $ docker exec -it web_container sh # 进入容器
    $ ping app_container.app # 在容器内执行,注意返回的IP不应是127.0.x.x
    PING app_container.app (172.19.0.2): 56 data bytes
    64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.434 ms
    ...
    $ exit # 退出容器
  • 再次查看网络webapp下的所有容器,特别注意有什么变化?

    1
    2
    $ docker network inspect web
    $ docker network inspect app

跨主机的容器网络通信

在Docker 1.9版本之前,要实现跨主机的容器间网络通信,需要借助第三方网络插件的支持,网络插件在很大程度上降低不同类型主机上容器通信的难度,扩展由Docker提供的核心网络功能。

而在Docker 1.9之后的版本中,Docker官方集成了重叠网络的特性,即支持创建虚拟网络并将其连接到容器上,可实现多个主机上容器相互通信,并且实现不同的应用程序或者应用程序不同部分能够相互隔离,互联子系统设计为可插拔式,兼容VXLAN或者IPVLAN等技术。
图片来自网络

目前,Docker容器实现跨主机通信主要通过以下方式:

而这里将重点介绍自带Overlay Network组件和Docker Swarm的实现方式,首先启动一台虚拟机模拟Node1,将主机模拟为Node2。

初始化 Docker Swarm
  • 在Node1上初始化并创建Docker Swarm,作为Manager。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ docker swarm init --advertise-addr 192.168.56.102
    Swarm initialized: current node (s08ktyv5yij5v7tu66t1ll2fi) is now a manager.
    To add a worker to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-68zbx1wtxgklsj36y3yjq90h6jcx2hewloku685fkvd44m9hw7-acgn20k3ary37fbd2mgtdf9t5 \
    192.168.56.102:2377
    To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
  • 在Node2上运行如下命令加入到Swarm中,作为Worker。

    1
    2
    3
    4
    $ docker swarm join \
    > --token SWMTKN-1-68zbx1wtxgklsj36y3yjq90h6jcx2hewloku685fkvd44m9hw7-acgn20k3ary37fbd2mgtdf9t5 \
    > 192.168.56.102:2377
    This node joined a swarm as a worker.

    也可以通过命令docker swarm join-token worker再次查看其token和IP。

  • 在Node1上查看当前所有Node信息

    1
    2
    3
    4
    $ docker node ls
    ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
    3r8p73yl8rkxkyiocnlxzc4wy moby Ready Active
    s08ktyv5yij5v7tu66t1ll2fi * localhost.localdomain Ready Active Leader
创建 Overlay Network
  • 在Node1上创建Overlay网络命名为net_overlay

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ docker network create -d=overlay net_overlay
    n9n1no3w0uku2lgn5jo5czc0l
    $ docker network ls
    NETWORK ID NAME DRIVER SCOPE
    694d3a222895 bridge bridge local
    64f31cf05fee docker_gwbridge bridge local
    22b5291ac1fb host host local
    yhb42l4f7a6q ingress overlay swarm
    n9n1no3w0uku net_overlay overlay swarm
    b76cb60af763 none null local

    这样,所有在Swarm中的主机都可以访问该网络了,除了docker0默认网桥外,这里多出了一个docker_gwbridge的网桥,docker0在跨多主机容器网络中并没有被用到,而是docker_gwbridge替代了docker0用来实现Overlay网络中容器间的通信以及容器到外部的通信,其职能就和单机容器网络中docker0一样。

  • 查看net_overlay网络的配置信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    $ docker network inspect net_overlay
    [
    {
    "Name": "net_overlay",
    "Id": "n9n1no3w0uku2lgn5jo5czc0l",
    "Scope": "swarm",
    "Driver": "overlay",
    "EnableIPv6": false,
    "IPAM": {
    "Driver": "default",
    "Options": null,
    "Config": [
    {
    "Subnet": "10.0.0.0/24",
    "Gateway": "10.0.0.1"
    }
    ]
    },
    ...
启动服务并测试连接
  • 创建服务并启动容器

    1
    2
    3
    4
    5
    $ docker service create --name hello --network net_overlay --replicas 2 ubuntu sleep infinity
    j56ia0rkjtc39eds80rt3yh4v
    $ docker service ls
    j56ia0rkjtc3 hello replicated 1/2 ubuntu:latest

    这里,创建了一个名为hello的服务,并绑定到net_overlay网络上,同时创建两个容器副本以sleep infinity的命令运行,该命令使得容器不会立即退出,两个容器分别会运行在两个节点为上。

  • 查看容器运行状态

    1
    2
    3
    $ docker service ps hello
    4fla3n6yogkk hello.1 ubuntu:latest localhost.localdomain Running
    p4adrd04a94y hello.2 ubuntu:latest moby Running

然后使用docker ps命令分别在Node1和Node2上查看容器信息获得容器ID,再通过inspect命令分别查看两个节点上的容器IP地址,使用exec命令登录到其中任意一个节点的容器内,使用pingtraceroute命令测试是否能连接到另一个节点上的容器,如果没有ping命令可以执行命令apt-get update; apt-get install iputils-ping -y安装即可。

小结

主要介绍了Docker网络相关的内容,包括Docker的网络实现原理、容器网络模型组件与优势、桥接网络与重叠网络的概念、Docker的四种网络方式、Docker网络端口映射、软件定义网络概念等,同时还练习了Docker网络基本命令,配置了同主机的容器虚拟网络,以及搭建了跨主机的容器虚拟网络。在整体和细节上都对Docker网络有了一个更清晰的认识,同时也对Docker网络相关命令更加熟练,能够配置同主机上的容器网络,并且也能够搭建跨主机的容器网络环境。


References