Docker⽹络详解——原理篇
前⾔
当你开始⼤规模使⽤Docker时,你会发现需要了解很多关于⽹络的知识。Docker作为⽬前最⽕的轻量级容器技术,有很多令⼈称道的功能,如Docker的镜像管理。然⽽,Docker同样有着很多不完善的地⽅,⽹络⽅⾯就是Docker⽐较薄弱的部分。因此,我们有必要深⼊了解Docker的⽹络知识,以满⾜更⾼的⽹络需求。本⽂⾸先介绍了Docker⾃⾝的4种⽹络⼯作⽅式,然后介绍⼀些⾃定义⽹络模式。
安装Docker时,它会⾃动创建三个⽹络,bridge(创建容器默认连接到此⽹络)、 none 、host
⽹络模式简介
Host容器将不会虚拟出⾃⼰的⽹卡,配置⾃⼰的IP等,⽽是使⽤宿主机的IP和端⼝。
Bridge此模式会为每⼀个容器分配、设置IP等,并将容器连接到⼀个docker0虚拟⽹桥,通过docker0⽹桥以及Iptables nat表配置与宿主机通信。
None该模式关闭了容器的⽹络功能。
Container创建的容器不会创建⾃⼰的⽹卡,配置⾃⼰的IP,⽽是和⼀个指定的容器共享IP、端⼝范围。
⾃定义⽹络略
⼀、默认⽹络
当你安装Docker时,它会⾃动创建三个⽹络。你可以使⽤以下docker network ls命令列出这些⽹络:
[root@server1 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
0147b8d16c64        bridge              bridge              local
2da931af3f0b        host                host                local
63d31338bcd9        none                null                local
Docker内置这三个⽹络,运⾏容器时,你可以使⽤该–network标志来指定容器应连接到哪些⽹络。
该bridge⽹络代表docker0所有Docker安装中存在的⽹络。除⾮你使⽤该docker run --network=选项指定,否则Docker守护程序默认将容器连接到此⽹络。
我们在使⽤docker run创建Docker容器时,可以⽤ --net 选项指定容器的⽹络模式,Docker可以有以下4种⽹络模式:
host模式:使⽤ --net=host 指定。
none模式:使⽤ --net=none 指定。
bridge模式:使⽤ --net=bridge 指定,默认设置。
container模式:使⽤ --net=container:NAME_or_ID 指定。
下⾯分别介绍⼀下Docker的各个⽹络模式。
1.1 Host模式
相当于Vmware中的桥接模式,与宿主机在同⼀个⽹络中,但没有独⽴IP地址。
众所周知,Docker使⽤了Linux的Namespaces技术来进⾏资源隔离,如PID Namespace隔离进程,Mount Namespace隔离⽂件系统,Network Namespace隔离⽹络等。
⼀个Network Namespace提供了⼀份独⽴的⽹络环境,包括⽹卡、路由、Iptable规则等都与其他的Network Namespace隔离。⼀个Docker容器⼀般会分配⼀个独⽴的Network Namespace。但如果启动容器的时候使⽤host模式,那么这个容器将不会获得⼀个独⽴的Network Namespace,⽽是和宿主机共⽤⼀个Network Namespace。容器将不会虚拟出⾃⼰的⽹卡,配置⾃⼰的IP等,⽽是使⽤宿主机的IP和端⼝。
例如,我们在172.25.6.1/24的机器上⽤host模式启动⼀个ubuntu容器
[root@server1 ~]# docker run -it --network=host ubuntu
可以看到,容器的⽹络使⽤的时宿主机的⽹络,但是,容器的其他⽅⾯,如⽂件系统、进程列表等还是和宿主机隔离的。
1.2 Container模式
在理解了host模式后,这个模式也就好理解了。这个模式指定新创建的容器和已经存在的⼀个容器共
享⼀个Network Namespace,⽽不是和宿主机共享。新创建的容器不会创建⾃⼰的⽹卡,配置⾃⼰的IP,⽽是和⼀个指定的容器共享IP、端⼝范围等。同样,两个容器除了⽹络⽅⾯,其他的如⽂件系统、进程列表等还是隔离的。两个容器的进程可以通过lo⽹卡设备通信。
1.3 None模式
该模式将容器放置在它⾃⼰的⽹络栈中,但是并不进⾏任何配置。实际上,该模式关闭了容器的⽹络功能,在以下两种情况下是有⽤的:容器并不需要⽹络(例如只需要写磁盘卷的批处理任务)。
overlay
在docker1.7代码进⾏了重构,单独把⽹络部分独⽴出来编写,所以在docker1.8新加⼊的⼀个overlay⽹络模式。Docker对于⽹络访问的控制也是在逐渐完善的。
1.4 Bridge模式
相当于Vmware中的Nat模式,容器使⽤独⽴network Namespace,并连接到docker0虚拟⽹卡(默认模式)。通过docker0⽹桥以及Iptables nat表配置与宿主机通信;bridge模式是Docker默认的⽹络设置,此模式会为每⼀个容器分配Network Namespace、设置IP 等,并将⼀个主机上的Docker容器连接到⼀个虚拟⽹桥上。下⾯着重介绍⼀下此模式。
⼆、Bridge模式
2.1 Bridge模式的拓扑
当Docker server启动时,会在主机上创建⼀个名为docker0的虚拟⽹桥,此主机上启动的Docker容器会连接到这个虚拟⽹桥上。虚拟⽹桥的⼯作⽅式和物理交换机类似,这样主机上的所有容器就通过交换机连在了⼀个⼆层⽹络中。接下来就要为容器分配IP了,Docker会从RFC1918所定义的私有IP⽹段中,选择⼀个和宿主机不同的IP地址和⼦⽹分配给docker0,连接到docker0的容器就从这个⼦⽹中选择⼀个未占⽤的IP使⽤。如⼀般Docker会使⽤172.17.0.0/16这个⽹段,并将172.17.0.1/16分配给docker0⽹桥(在主机上使⽤ifconfig命令是可以看到docker0的,可以认为它是⽹桥的管理接⼝,在宿主机上作为⼀块虚拟⽹卡使⽤)。单机环境下的⽹络拓扑如下,主机地址为10.10.0.186/24。
2.2 Docker:⽹络模式详解
Docker完成以上⽹络配置的过程⼤致是这样的:
(1)在主机上创建⼀对虚拟⽹卡veth pair设备。veth设备总是成对出现的,它们组成了⼀个数据的通道,数据从⼀个设备进⼊,就会从另⼀个设备出来。因此,veth设备常⽤来连接两个⽹络设备。
(2)Docker将veth pair设备的⼀端放在新创建的容器中,并命名为eth0。另⼀端放在主机中,以veth
65f9这样类似的名字命名,并将这个⽹络设备加⼊到docker0⽹桥中,可以通过brctl show命令查看。
brctl show
bridge name    bridge id              STP enabled    interfaces
docker0        8000.02425f21c208      no
(3)从docker0⼦⽹中分配⼀个IP给容器使⽤,并设置docker0的IP地址为容器的默认⽹关。
运⾏容器:
docker run --name=nginx_bridge --net=bridge -p 80:80 -d nginx
9582dbec7981085ab1f159edcc4bf35e2ee8d5a03984d214bce32a30eab4921a
查看容器:
docker ps
CONTAINER ID        IMAGE          COMMAND                  CREATED            STATUS              PORTS                NAMES
9582dbec7981        nginx          "nginx -g 'daemon ..."  3 seconds ago      Up 2 seconds        0.0.0.0:80->80/tcp  nginx_bridge
# 查看容器⽹络;
docker inspect 9582dbec7981
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "9e017f5d4724039f24acc8aec634c8d2af3a9024f67585fce0a0d2b3cb470059",
"EndpointID": "81b94c1b57de26f9c6690942cd78689041d6c27a564e079d7b1f603ecc104b3b",
"Gateway": "172.17.0.1",
docker进入容器"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
docker network inspect bridge
[
{
"Name": "bridge",
"Id": "9e017f5d4724039f24acc8aec634c8d2af3a9024f67585fce0a0d2b3cb470059",
"Created": "2019-06-09T23:20:28.061678042-04:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"Containers": {
"9582dbec7981085ab1f159edcc4bf35e2ee8d5a03984d214bce32a30eab4921a": {
"Name": "nginx_bridge",
"EndpointID": "81b94c1b57de26f9c6690942cd78689041d6c27a564e079d7b1f603ecc104b3b",                "MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.dockerwork.bridge.default_bridge": "true",
"com.able_icc": "true",
"com.able_ip_masquerade": "true",
"com.dockerwork.bridge.host_binding_ipv4": "0.0.0.0",
"com.dockerwork.bridge.name": "docker0",
"com.u": "1500"
},
"Labels": {}
}
]
⽹络拓扑介绍完后,接着介绍⼀下bridge模式下容器是如何通信的。
2.3 bridge模式下容器的通信

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。