Docker在创建容器的时候,可以使用--net选项指定容器的的网络模式。

网络模式

Docker支持4种网络模式供大家选择:

  • host模式,使用- -net=host指定。
  • container模式,使用- -net=container:NAME_or_ID指定。
  • none模式,使用- -net=none指定。
  • bridge模式,使用- -net=bridge指定,默认设置。

host模式

众所周知,Docker使用了LinuxNamespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡路由Iptable规则等都与其他的Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。

例如,我们在10.10.101.105/24的机器上用host模式启动一个含有web应用的Docker容器,监听tcp80端口。当我们在容器中执行任何类似ifconfig命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用10.10.101.105:80即可,不用任何NAT转换,就如直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

container模式

在理解了host模式后,这个模式也就好理解了。这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。

none模式

这个模式和前两个不同。在这种模式下,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。

bridge模式

bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。

bridge模式的拓扑

Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。接下来就要为容器分配IP了,Docker会从RFC1918所定义的私有IP网段中,选择一个和宿主机不同的IP地址和子网分配给docker0,连接到docker0的容器就从这个子网中选择一个未占用的IP使用。如一般Docker会使用172.17.0.0/16这个网段,并将172.17.42.1/16分配给docker0网桥(在主机上使用ifconfig命令是可以看到docker0的,可以认为它是网桥的管理接口,在宿主机上作为一块虚拟网卡使用)。单机环境下的网络拓扑如下,主机地址为10.10.101.105/24

bridge的拓扑
bridge的拓扑

-

bridge的拓扑
bridge的拓扑

-

默认模式

安装完Docker的时候,会自动创建三个网络。使用docker network ls命令可以查看这些网络:

1
2
3
4
5
6
$ docker network ls               

NETWORK ID NAME DRIVER SCOPE
75b73b341642 bridge bridge local
dbef3961eb84 host host local
90741a2555ee none null local

这三个网络都建在Docker中。运行容器时,可以使用该--network标志来指定容器应连接到的网络。

默认网桥

Docker 服务启动后默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。

Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了 MTU(接口允许接收的最大传输单元),通常是 1500 Bytes,或宿主主机网络路由上支持的默认值。这些值都可以在服务启动的时候进行配置。

bridge所有Docker主机上都存在默认网络。如果您不指定其他网络,则新的容器会自动连接到默认bridge网络。

使用docker network inspect命令可以查看相关的网络信息:

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
$ docker network inspect 75b73b341642

[
{
"Name": "bridge",
"Id": "75b73b3416429364a268ba6db607cb6bffbc921241714228d22fd95c15cde76f",
"Created": "2019-01-01T05:13:00.609463Z",
"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,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"1bd6dc5dbb7c6a73801ce682d4fe590cff14ba046837c75de70b7a2f756cdd21": {
"Name": "boring_nash",
"EndpointID": "060084e59605428932e9862193ede495b23459d4d8039b1ef4e0f25099726599",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"3dc606b07fbbbc2e2040104764b81cf6fbccf1594f4da99fcf03264ad2fcb9d6": {
"Name": "rabbitmq",
"EndpointID": "08031fb6659f74caa2940d473f3c5ccbc849a5af485361705e63c3df66927e8c",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"4b8887d1cf1cbe7c8d17990d2c91dce95f7099e9a9f178b6feed525b7879a369": {
"Name": "objective-mysql",
"EndpointID": "9732e3b010e7053cf8e3d0f0985e5e26557d75a4930d100452ac71c5e97ecc15",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/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": {}
}
]