docker网络篇

1、四个网络
定义:docker安装时会自动在host上创建三个网络,可以通过docker network ls命令查看

upload successful
(1)none网络
定义:顾名思义,none网络就是什么都没有的网络。挂在这个网络下的容器除了lo,没有其他任何网卡。容器创建时,可以通过–network=none指定使用none网络。

应用场景:封闭意味着隔离,一些对安全性要求高并且不需要联网的应用可以使用none网络。比如某个容器的唯一用途就是生成随机密码,就可以放到none网络中避免密码被窃取。

命令:指定使用none网络

upload successful

(2)host网络
定义:连接到host网络的容器共享docker host的网络栈,容器的网络配置与host完全一样。可以通过–network=host来指定使用host网络。

应用场景:直接使用docker host网络的最大好处就是性能,如果容器对网络传输效率有较高要求,则可以选择host网络。当然不便之处就是牺牲一些灵活性,比如要考虑端口冲突问题,docker host上已经使用的端口就不能再使用了。

命令:指定使用host网络

upload successful
容器的hostname也跟宿主机一样

upload successful

(3)bridge网络(默认)
定义:docker安装时会创建一个命名为docker0的linux bridge。如果不指定–network,创建的容器默认都会挂到docker0上。

命令:一个新的网络接口vethad723e1被挂到了docker0上,vethad723e1就是新创建容器的虚拟网卡。

upload successful
查看容器的网络配置

upload successful
对比docker0和容器的interface,实际上vethad723e1和eth0@if109是一对veth pair。veth pair是一种成对出现的特殊网络设备,可以把它们想象成由一根虚拟网线连接起来的一对网卡,网卡的一头(eth0@if109)在容器中,另一头(vethad723e1)挂在网桥docker0上,其效果就是将eth0@if109 也挂在了 docker0 上。其中,eth0@if109的ip地址是172.17.0.3/16,这个网段的ip是由bridge网络的配置决定的。
查看bridge网络的配置信息

upload successful

(4)自定义网络
定义:除了none、host、bridge这三个自动创建的网络,用户也可以根据业务需要创建user-defined网络。docker提供了三种user-defined网络驱动:bridge、overlay和macvlan。

命令:新增了一个网桥br-30ff061f03ca

upload successful
查看my_net的配置信息

upload successful
除了可以自动分配,还可以自定义ip网段

upload successful
容器使用新的网络,使用自动分配的ip

upload successful
除了可以自动分配,还可以指定ip地址

upload successful
备注:
只有使用–subnet创建的网络才能指定静态ip。如果容器使用不是–subnet创建的网络,指定ip地址时会返回错误。

upload successful

2、容器与容器的相互访问
同一网络之间的容器通信:有三种通信方式
(1)IP
两个容器要能通信,必须要有属于同一网络的网卡。具体做法是在创建容器时通过–network指定相应的网络,或者通过docker network connect将现有网络加入到指定网络。参考之前的章节。
(2)docker dns server
通过ip访问会有一个问题:我们在部署应用之前有可能无法确定ip,部署之后再指定要访问的ip会比较麻烦。针对这个问题,可以通过docker自带的dns服务来解决。
原理:从docker1.10版本开始,docker daemon实现了一个内嵌的dns server,使容器可以直接通过容器名通信。方法很简单,只要在启动时使用–name为容器命名就可以了。
实验一:
启动两个容器:
docker run -it –network=my_net2 –name=bbox1 busybox
docker run -it –network=my_net2 –name=bbox2 busybox
验证ping测试:

upload successful
结论:可以ping通。

实验二:
创建两个bridge网络下的容器:
docker run -it –name=bbox3 busybox
docker run -it –name=bbox4 busybox
验证ping测试:

upload successful
结论:使用dns有限制,只能在自定义网络(my_net2就是自定义网络)中使用。也就是说,默认的bridge网络是无法使用dns的。
(3)joined
原理:可以使两个或多个容器共享一个网络栈、网卡和配置信息,joined容器之间可以通过127.0.0.1直接通信
适用场景:
不同容器中的程序希望通过loopback高效快速的通信,比如web server与app server;希望监控其他容器的网络流量,比如运行在独立容器中的网络监控程序。
验证:
先创建一个httpd容器,名字为web1:
docker run -d -it –name=web1 httpd
然后创建busybox容器并通过–network=container:web1指定joined容器为web1

upload successful
查看web1容器的网络配置信息:

upload successful
结论:busybox与web1的网卡mac地址与ip地址完全一样,它们共享了相同的网络栈。

不同网络之间的容器通信:
首先,由常识可知,同一网络中的容器、网关之间都是可以相互通信的。也可以通过实验验证。但是,自定义网络(my_net2)与默认bridge网络之间默认不能相互通信。针对这个问题,我们可以通过添加路由来达到不同网络之间的同期也能相互通信的目的。也就是说,如果host上针对每个网络都有一条路由,同时操作系统上打开了ip forwarding,host就成了一个路由器,挂接在不同网桥上的网络就能够相互通信。
验证:
首先,定义172.17.0.0/16和172.22.16.0/24两个网络的路由:

upload successful
确认打开了ip转发功能:
sysctl net.ipv4.ip_forward
或者cat /proc/sys/net/ipv4/ip_forward,值为1表示打开了ip转发功能
为httpd容器(位于bridge网络)添加一块my_net2的网卡,添加命令:

upload successful
在httpd容器中查看网络配置(红框中为新加的网卡,ip地址是my_net2端随机分配的ip,这时候就可以在位于my_net2的容器ping通httpd容器):

upload successful

容器与外部的相互访问:
(1)容器访问外部
定义:容器默认就能访问外网(外网指的是容器网络以外的网络环境,并非特指Internet)
原理:最关键的就是NAT技术
验证
首先,查看一下host的iptables规则:

upload successful
这条iptables规则的含义:
如果网桥 docker0 收到来自 172.17.0.0/16 网段的外出包,把它交给 MASQUERADE 处理。而 MASQUERADE 的处理方式是将包的源地址替换成 host 的地址发送出去,即做了一次网络地址转换(NAT)。
通过tcpdump查看地址转换:
首先,查看host的路由表:
默认路由通过eth0发送出去,所以我们可以通过tcpdump来监控docker0和eth0上的icmp数据包

upload successful
然后,在busybox容器上ping外网(比如www.bing.com),tcpdump输出如图:
docker0 收到 busybox 的 ping 包,源地址为容器 IP 172.17.0.4,然后交给 MASQUERADE 处理。

upload successful
这时在eth0上查(发现ping包的源地址变成了144.34.204.150)

upload successful

(2)外部访问容器
原理:端口映射
验证
首先,docker可以将容器对外提供服务的端口映射到host的某个端口,外网通过该端口访问容器。

upload successful
容器启动后,可以通过docker ps或者docker port查看到host映射的端口。在上面的例子中,httpd容器的80端口被映射到host 32769上,这样就可以通过 :<32769> 访问容器的 web 服务了。
也可以指定映射到host的某个特定端口:

upload successful
每一个映射的端口,host都会启动一个docker-proxy进程来处理访问容器的流量:

upload successful

最后,过程总结:
docke-proxy监听host的32769端口;
当访问宿主机的web服务的时候(宿主机的ip:port),docker-proxy 转发给容器(容器ip:容器port);
httpd 容器响应请求并返回结果。