Docker 网络从覆盖范围可分为单个Host上的容器网络和跨多个host的网络,Docker安装时会自动在host上创建三个网络
可以用docker network ls查看
顾名思义,none网络就是什么都没有的网络,挂载这个网络下的容器除了lo,就没有其他的任何网卡。我们在创建容器时,可以通过--network=none指定使用none网络
用处:
某个容器的唯一途径是生成随机密码,就可以放到none网络中避免密码被窃取
连接到host网络的容器共享docker host的网络栈,容器的网络配置与host完全一样,可以通过--network=host指定使用host网络
在容器中可以看到host的所有网卡,并且容器的hostname也是host的。
使用场景:
直接使用Docker host的网络最大的好处就是性能,如果容器对网络传输效率有较高的要求,则可以选择host网络。不便之处就是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host上已经使用的端口就不能再使用了。
Docker host 的另一个用途就是让容器可以直接配置host网络,比如某些跨host的网络解决方案,其本身也是以容器方式运行的,这些方案需要对网络进行配置,比如管理iptables
Docker安装时会创建一个名为docekr0的linux bridge。如果不指定--network,创建的容器默认都会挂载到docker0上
可以通过brctl show 查看
我们通过创建一个容器来查看
可以看到一个新的网络接口veth3120194被挂载到了docker0上,veth3120194就是新创建容器的虚拟网卡
我们可以进入容器查看:
我们会看到容器中有一个eth0的网卡,而这个eth0和veth3120194是一对veth pair,
Veth pair是一种成对出现的特殊网络设备,可以把它们想像成由一根网线连起来的一对网卡,网卡的一头eth0在容器中,另一头veth3120194挂在网桥docker0上。
我们还可以看到eth0有一个IP地址:172.17.0.2。
可以通过docker network inspect bridge查看bridge配置信息可以看到bridge网络配置的subnet就是172.17.0.0/16,并且网关是172.17.0.1,这个网关就是docker0,我们也可以通过linux宿主机的命令查看docker0
User-defined网络:
除了none、host、bridge这三个自动创建的网络,我们也可以根据业务需要创建user-defined网络。
Docker提供三种user-defined的网络驱动:bridge、overlay和macvlan。Overlay和macvlan用于创建跨主机的网络。
我们可以通过bridge驱动创建类似默认的bridge网络:
查看当前host的网络结构变化:
发现新增了一个br-925a02635f42,而这个正是新建的bridge网络的my_net的短ID,可以执行docker network inspect查看my_net的配置信息:
我们可以看到:172.18.0.0/16,这个是Docker自动分配的IP网段以及:172.18.0.1是自动分配的网关。
我们也可以在创建网段是指定--subnet和--gateway:
我们所创建的新的bridge网络my_net2,网段为192.168.10.0/24,网关为:192.168.10.1。
网关在my_net2对应的网桥br-ea2dc90b762f上可通过ifconfig查看:
而我们的容器要使用新的网络,只需要在启动时通过--network指定:
此时我们的centos1容器所分配到的IP地址为:192.168.10.2,截止到现在,我们的所有的容器都是自动从subnet中分配的IP,当然我们也可以自己指定一个静态IP
通过--ip来指定我们要分配的IP地址:
当然自动指定IP也是有要求的,只有我们在创建网络是使用了--subnet时我们才可以指定静态IP。(我们创建my_net2时指定了192.168.10.0/24的网段)
我们可以试一下之前创建的my_net:(在前面创建时我们知道了my_net的IP段为172.18.0.0/16)
可以看到给我们报了一个错误:(错误意思:来自守护程序的错误响应:仅当连接到具有用户配置的子网的网络时,才支持用户指定的IP地址)
我们看一下docker的网络拓扑结构:
(图中busybox为实验中的centos.net)
两个busybox容器都挂在my_net2上,它们是可以互相通信的,而my_net2与默认的bridge是不能通信的,从上图可知两个网络属于不同的网桥。
当然我们的host对每个网络都有一条路由,同时操作系统打开了ip forwarding,host就成了一个路由器,可以通过ip r 查看host上的路由表:
在查看我们是否启用了ip forwarding:
其次我们就应该检查我们的防火墙了:可以通过iptables-save来查看
从规则命名DOCKER-ISOLATION可以知道docker在设计上就是要隔离不同的network,我们可以思考如何让他们互相通信呢?
容器里给一个解决方案:可以为centos3容器添加一块net_my2的网卡,可以通过docker network connect命令实现:
可以发现容器中增加了一个eth1的网卡,并且分配了my_net2的IP:192.168.10.3,然后我们在ping一下:
可以发现它们已经可以通信。
当前网络拓扑图:
下面讨论容器间通信:
前面的例子我们可以得出一个结论:两个容器要能通信,必须要有属于同一个网络的网卡。满足这个条件后容器就可以通过IP交互了,
我们通过--network制定相应的网络
通过docker network connect 将现有容器加入指定网络
Docker DNS Server:
通过IP访问容器已经满足了通信的要求,但还是不够灵活。因为我们部署应用之前无法确定IP,部署之后再指定要访问的IP会比较麻烦,而这个问题我们可以使用docker自带的DNS解决。
Docker daemon自Docker 1.10版本开始,实现了一个内嵌的DNS server,使容器可以直接通过“容器名”通信。我们只需要在启动容器是用--name为容器命名
但使用docker DNS有个限制:只能在user-defined网络中使用,也就是默认的bridge网络时无法使用DNS的
Joined容器:
Joined容器是另一种实现容器之间通信的方式。
Joined容器非常特别,它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,容器可以通过127.0.0.1直接通信:
Joined适用于以下场景:
不同容器中的程序希望通过loopback高效快速地通信,比如Web Server与App Server
希望监控其他容器的网络流量,比如运行在独立容器中的网络监控程序
将容器与外部世界连接:
我们当前Host是可以访问外网的
我们看一下容器是否也可以:
可以看到,容器默认就可以访问外网。
我们来理解一下这个现象的本质:
我们centos1位于bridge网络中,当我们centos1从容器往外ping时,数据包是通过NAT来转换的,我们可以看一下Host上的iptables:
我们通过iptables -t nat -S查看:
有这么一条规则:
含义为:如果网桥br-ea2dc90b762f收到来自192.168.10.0/24网段的外出包,则把它交给MASQUERADE处理,而MASQUERADE的处理方式是将包的源地址替换成Host的地址发送出去,即做了一次网络地址转换(NAT)
外界访问容器:
外面访问我们容器的方法则是端口映射:
Docker可以将对外提供服务的端口映射到host的某个端口,外网通过改端口访问容器。
例如httpd,我们可以通过-p来指定80端口映射到主机80端口,然后就可以通过访问主机访问到我们的httpd服务了。
原文:https://www.cnblogs.com/xxknight/p/11754622.html