docker通信原理

Docker的本地网络实现其实就是利用了Linux上的网络命名空间和虚拟网络设备(特别是veth pair)

一般情况下,Docker创建一个容器的时候,会具体执行如下操作:
1.创建一对虚拟接口,分别放到本地主机和新容器的命名空间中;
2.本地主机一端的虚拟接口连接到默认的docker0网桥或指定网桥上,并具有一个以veth开头的唯一名字,如veth1234;
3.容器一端的虚拟接口将放到新创建的容器中,并修改名字作为eth0。这个接口只在容器的命名空间可见;
4.从网桥可用地址段中获取一个空闲地址分配给容器的eth0(例如172.17.0.2/16),并配置默认路由网关为docker0网卡的内部接口docker0的IP地址(例如172.17.42.1/16)。
完成这些之后,容器就可以使用它所能看到的eth0虚拟网卡来连接其他容器和访问外部网络。用户也可以通过docker network命令来手动管理网络


docker网络模式
安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络,也就是在不使用--network参数时)、 none 、host。还有后一种自定义模式,自定义模式有三种:bridge、overlay、macvlan。

host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
Container:创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。
None:该模式关闭了容器的网络功能。
Bridge:此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。

通过docker network ls可以查看docker网络:

容器之间的通信
容器之间可通过 IP,Docker DNS Server 和joined 容器三种方式通信。

IP 通信
两个容器要能通信,必须要有属于同一个网络的网卡。满足这个条件后,容器就可以通过 IP 交互了。具体做法是在容器创建时通过 --network 指定相应的网络,或者通过 docker network connect 将现有容器加入到指定网络。

Docker DNS Server
通过 IP 访问容器虽然满足了通信的需求,但还是不够灵活。因为我们在部署应用之前可能无法确定 IP,部署之后再指定要访问的 IP 会比较麻烦。对于这个问题,可以通过 docker 自带的 DNS 服务解决。
从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过"容器名"通信。方法很简单,只要在启动时用 --name 为容器命名就可以了。
#使用 docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是无法使用 DNS 的

joined 容器
joined 容器是另一种实现容器间通信的方式。它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined 容器之间可以通过 127.0.0.1 直接通信

容器访问控制
容器的访问控制主要通过Linux上的iptables防火墙软件来进行管理和实现。iptables是Linux系统流行的防火墙软件,在大部分发行版中都自带。


1.容器访问外部网络
我们知道容器默认指定了网关为docker0网桥上的docker0内部接口。docker0内部接口同时也是宿主机的一个本地接口。因此,容器默认情况下是可以访问到宿主机本地的。更进一步,容器要想通过宿主机访问到外部网络,需要宿主机进行转发。

如果为0,则没有开启转发,则需要手动打开:
# sysctl -w net.ipv4.ip_forward=1
更简单的,在启动Docker服务的时候设定--ip-forward=true,Docker服务会自动打开宿主机系统的转发服务。

2.外部访问容器实现
容器允许外部访问,可以在docker run时候通过-p或-P参数来启用。

不管用那种办法,其实也是在本地的iptable的nat表中添加相应的规则,将访问外部IP地址的网包进行目标地址DNAT,将目标地址修改为容器的IP地址。

发布了201 篇原创文章 · 获赞 85 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/Doudou_Mylove/article/details/100771775