Docker网络

Docker网络

      Docker安装时会自动在host上创建bridge、host、none这三个网络,可以用docker network ls命令来查看

 

none网络

      none网络就是什么网络都没有,挂在这个网络下的容器除了lo,没有其他任何网卡,创建容器时可以通过--network=none来指定使用none网络。对一些安全性要求高并且不需要联网的应用可以使用none网络。除此之外,我们要实现容器的集中管控也可以使用none网络,比如要使所创建的网络受控于SDN网络,则可以先用none网络来启动容器,然后再将该网络连接到OVS的网桥上,使其受控于SDN的控制器 

 

host网络

      连接到host网络的容器共享Docker host的网络栈,容器的网卡配置与host完全一致,可以通过--network=host来指定使用host网络。直接使用Docker host的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,则可用host网络,但它的灵活性不高,比如要考虑端口冲突的问题,Docker host上已经使用的端口则不能再使用。它的另一个用途是让容器可以直接配置host网络,比如某些跨主机的网络 

 

bridge网络

      Docker安装时会创建一个命名为docker0的linux bridge,如果不指定--network,创建的容器默认都会挂到docker0上,可以使用docker network inspect bridge查看网络的配置信息。容器创建时,docker会自动从172.17.0.0/16中分配一个IP,这里16位掩码保证有足够多的IP可以供容器使用

  

user-defined网络

      Docker提供三种user-defined网络驱动:bridge、overlay和macvlan。其中overlay和macvlan用于创建跨主机的网络

      可以通过bridge驱动创建类似前面默认的bridge网络,这里的172.18.0.0/16是Docker自动分配的IP网段 

      也可以自己指定IP网段,只需在创建网段时指定--subnet和--gateway参数,下面来创建一个新的bridge网络mynet1,网段为172.22.16.0/24,网关为172.22.16.1

 

      用创建的mynet1网络来启动一个容器并查看它的IP地址,可以看到容器已经被分配到IP为172.22.16.2

 

      Docker创建容器时都是自动从subnet中分配IP,我们也可以给容器指定一个静态IP,用--ip参数来实现

      需要注意的是,只有使用--subnet创建的网络才能指定静态IP,前面创建mynet网络时并没有使用--subnet,如果使用mynet网络来指定静态IP,则会出错 

 

      如果我们不再需要自定义创建的网络时,也可以删除它们 

 

      接下来来验证各个主机之间的连通性,由于上面创建的主机比较多,而且每个各个主机可能在不同的网络类型下,为了更加直观的看出主机间的网络情况,这里绘制了一个简单的网络拓扑结构图

      host3和host4两个容器都挂在mynet1上,是可以相互通信的,下面来验证它们之间的连通性。由结果可以看出同一网络中的容器、网关之间都能相互通信

 

      mynet1与docker0属于不同的网桥,它们之间应该不能直接通信。下面来验证host3与host5之间的连通性。结果表明它们的确不能相互通信

 

      不同网络如果加上路由是可以通信的。用ip r来查看host上的路由表

      由路由表可以看出172.17.0.0/16和172.22.16.0/24两个网络的路由都定义好了

 

      查看ip forwarding 

      ip forwarding也已经启动

 

      虽然该有的条件已经满足,但不同网络还是无法通信,接下来查看iptables

sudo iptables-save

      原因就在这里:iptables DROP掉了网桥docker0与br-305c071332d6之间的双向流量。从规则的命名DOCKER-ISOLATION可知docker在设计上就是要隔离不同的network

 

      要实现host3与host5之间的通信,可以用一下方法:为host5容器添加一块mynet1的网卡,通过docker network connect命令实现 

 

      host5中查看网络配置

      可以看出容器中增加了一个网卡eth1,分配了mynet1的IP 172.22.16.3,现在host3与host5之间可以相互通信了,下面来验证它们的连通性 

 

容器间的三种通信方法

IP通信

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

 

Docker DNS Server

      IP通信的灵活性不高,因为部署应用前可能无法确定IP,部署后再指定要访问的IP会比较麻烦,解决这一问题的方法是通过docker自带的DNS服务。从Docker1.10版本开始,docker daemon实现了一个内嵌的DNS server,使容器可以直接通过“容器名”通信,方法很简单,只需在启动容器时用--name为容器命名就可以了 

      使用docker DNS有个限制:只能在user-defined网络中使用,默认的bridge网络是无法使用DNS的,下面看一个例子 

 

joined容器

      joined容器可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined容器间可以通过127.0.0.1直接通信

      joined容器适合以下场景

            1. 不同容器中程序希望通过loopback高效快速地通信,比如web server与app server

            2. 希望监控其他容器的网络流量,比如运行在独立容器中的网络监控程序

 

外部网络访问容器

      docker可将容器对外提供服务的端口映射到host的某个端口,外网通过该端口访问容器。容器启动时通过-p参数映射端口 

      容器启动后可以通过docker ps或docker port查看host映射的端口。上面例子中web2容器的80端口被映射到host的32768上,这样就可以在host上通过<host ip>:<32768>访问到容器的web服务 

 

      除了映射动态端口,也可在-p中指定映射到host某个特定端口。例如可将80端口映射到host的8080端口 

 

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

      以0.0.0.0:32768—>80/tcp为例分析整个过程

            1. docker-proxy监听host的32768端口

            2. 当curl访问127.0.0.1:32768时,docker-proxy转发给容器172.17.0.5:80

            3. httpd容器响应请求并返回结果

 

posted @ 2018-10-22 23:04  Chenjin2018  阅读(706)  评论(0编辑  收藏  举报