docker network

Posted 穷少年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了docker network相关的知识,希望对你有一定的参考价值。

文章目录

docker network是什么

容器网络实质上也是由Docker为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作系统的网络环境中独立出来,形成容器自有的网络设备、IP协议栈、端口套接字、IP路由表、防火墙等等与网络相关的模块。


Docker网络中有三个核心概念:沙盒(Sandbox)、网络(Network)、端点(Endpoint)。

  • 沙盒,提供了容器的虚拟网络栈,也即端口套接字、IP路由表、防火墙等内容。隔离容器网络与宿主机网络,形成了完全独立的容器网络环境。
  • 网络,可以理解为Docker内部的虚拟子网,网络内的参与者相互可见并能够进行通讯。Docker的虚拟网络和宿主机网络是存在隔离关系的,其目的主要是形成容器间的安全通讯环境。
  • 端点,位于容器或网络隔离墙之上的洞,主要目的是形成一个可以控制的突破封闭的网络环境的出入口。当容器的端点与网络的端点形成配对后,就如同在这两者之间搭建了桥梁,便能够进行数据传输了。
    这三者形成Docker网络核心模型,也就是容器网络模型(Container Network Model)。

docker的网络实现

容器网络模型为容器引擎提供了一套标准的网络对接范式,Docker中,实现这套范式的是Docker所封装的libnetwork模块。

Docker官方提供了五种Docker网络驱动,分别是:Bridge Driver、Host Driver、Overlay Driver、MacLan Driver、None Driver。Bridge和 Overlay在开发中使用频率较高。

网络模式简介
host(主机模式)相当于Vmware中的桥接模式,与宿主机在同一个网络中,但没有独立IP地址
bridge(桥梁模式)相当于Vmware中的Nat模式,容器使用独立network Namespace,并连接到docker0虚拟网卡(默认模式)。
overlay(覆盖模式)Overlay网络是指在不改变现有网络基础设施的前提下,通过某种约定通信协议,把二层报文封装在IP报文之上的新的数据格式。
container(容器模式)在理解了host模式后,这个模式也就好理解了。这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
none(无网络模式)该模式将容器放置在它自己的网络栈中,但是并不进行任何配置。实际上,该模式关闭了容器的网络功能,在以下两种情况下是有用的:容器并不需要网络(例如只需要写磁盘卷的批处理任务)。

1. 默认网络(docker0)

当你安装Docker时,它会自动创建三个网络。你可以使用以下docker network ls命令列出这些网络:

Docker内置这三个网络,运行容器时,你可以使用该–network标志来指定容器应连接到哪些网络。

该bridge网络代表docker0所有Docker安装中存在的网络。除非你使用该docker run --network=选项指定,否则Docker守护程序默认将容器连接到此网络。

2. 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和端口。

3. bridge网络模式(重点)

相当于Vmware中的Nat模式,容器使用独立network Namespace,并连接到docker0虚拟网卡(默认模式)。通过docker0网桥以及Iptables nat表配置与宿主机通信;bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。下面着重介绍一下此模式。

Docker 默认的 bridge 网络是不支持通过 Docker DNS 服务进行域名解析的,自定义桥接网络是可以的。

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。

Docker完成以上网络配置的过程大致是这样的:

(1)在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。
(2)Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在主机中,以veth65f9这样类似的名字命名,并将这个网络设备加入到docker0网桥中
(3)从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。

docker overlay模式

Overlay网络是指在不改变现有网络基础设施的前提下,通过某种约定通信协议,把二层报文封装在IP报文之上的新的数据格式。这样不但能够充分利用成熟的IP路由协议进程数据分发;而且在Overlay技术中采用扩展的隔离标识位数,能够突破VLAN的4000数量限制支持高达16M的用户,并在必要时可将广播流量转化为组播流量,避免广播数据泛滥。

因此,Overlay网络实际上是目前最主流的容器跨节点数据传输和路由方案。

要想使用Docker原生Overlay网络,需要满足下列任意条件

  • Docker 运行在Swarm
  • 使用键值存储的Docker主机集群

docker network指令

通过docker network指令,可以方便的管理docker服务器上的网络

docker network inspect			 # 根据网络的ID展示网络的详细信息
docker network ls				 # 展示所有的网络,以列表形式
docker network create			 # 创建一个自定义网络
docker network connect			 # 连接一个容器到指定网络上
docker network disconnect 		 # 让一个容器从指定网络上断开
docker network prune			 # 删除所有未使用的网络
docker network rm 				 # 根据网络的ID,删除一个或多个网络

自定义网络

  1. 自动DNS解析容器名称到IP地址,例如我们连接mysql服务器时,可以通过容器名:端口的形式,拼接url
  2. 方便管理,在同一网络下的主机可以相互连通

自定义网络(案例)

  • 创建一个自定义网络,subnet参数指定网络的范围以及网络前缀,--bridge指定网络的类型,--gateway指定当前网络的网关地址

  • 查看网络详情

  • 启动一个tomcat服务器,通过--network在启动时连接至自定义网络-
    我们启动完成后,发现tomcat已经连接至自定义网络

  • 启动一个centos系统 ,连接至自定义网络,以交互的方式启动,ping一下tomcat看能否ping

    我们发现,在同一网络下,两个容器之间可以相互访问

docker自定义网络搭建redis集群

  • 创建一个redis-net(自定义网络)

  • 按照下面的配置启动6个redis容器

    按照下面的命令依次运行

    启动成功

    查看redis-net网络详情,可以看出所有的redis容器都已经连接至一个网络

  • 进入任意redis容器内,使用redis-cli搭建集群,如下所示,可见集群已经搭建成功,注意:最好使用每个容器的IP进行搭建,如果使用容器名,会出现映射不成功的错误

–link(容器互联)

在容器运行启动的时候,通过--link参数可以指定容器之间相互绑定,以达到容器之间的项目访问
其实原理就是在/etc/hosts里面添加了一个alias的名称。

测试

1.启动两个容器,进行测试

# 启动第一个容器
docker run -d --name tomcat1 tomcat
# 启动第二个容器
docker run -d --name tomcat2 tomcat


2.任意进入一个tomcat容器内部,去ping另一个tomcat容器,发现ping不通

3.我们再启动一个tomcat03,使用–link参数链接到tomcat01,tomcat02

4.我们进入tomcat03容器内部,去pingtomcat01或tomcat02,发现tomcat03可以直接通过容器名访问其它两个容器

5.查看tomcat03的/etc/hosts文件,发现,其实是做了一个域名映射

结论:

  1. 两个容器间互相通信使用–link,可以实现互通。

  2. docker0 不支持容器名连接访问。

建议:

docker官方已不推荐使用docker run --link来链接2个容器互相通信,随后的版本中会删除–link,但了解其原理,对如何使2个容器之间互相通信还是有帮助。

参考文章

  1. Docker网络详解——原理篇
  2. 花了三天时间终于搞懂 Docker 网络了
  3. 「Docker」 - 容器网络

以上是关于docker network的主要内容,如果未能解决你的问题,请参考以下文章

Docker——Docker网络(Network)+ 部署Redis高可用集群

记一次linux Docker网络故障排除经历

docker 环境搭建redis集群相关问题

docker 环境搭建redis集群相关问题

Docker 监控的一点想法

[docker]docker网络最佳实战