docker网络追溯
前言
官网文档——docker网络
这里会采用简单的语言,大概的讲解一下docker网络的情况。
网络驱动
也可以称为网络连接模式。
查看当前主机的网络分布:
docker network ls
主要分为以下几种:
- bridge
桥接模式,也是docker默认的网络驱动,当你需要多个容器在同一个 Docker 主机上进行通信时,桥接网络是最佳选择。 - host
主机模式,顾名思义,就是容器和docker主机共用网络ip、端口,但是这样就降低了容器之间的隔离性,如果不要求隔离性,就采用这种模式,话说使用docker不就是看重它的隔离性吗…。 - none
对于容器,禁用所有网络。通常与自定义网络驱动程序一起使用。none不适用于 swarm 服务。 - overlay
在多个 Docker 主机之间创建一个分布式网络,实现互相通信,适合集群,比如docker swarm。
自定义NetWork网络
不指定类型,默认创建的就是桥接模式的网络bridge。
docker network create my-bridge
指定子网掩码创建
docker network create --subnet=172.18.0.0/24 my-bridge
docker network create -d overlay my-overlay
docker network create -d host my-host
docker network create -d none my-none
查看网络详情:
docker network inspect my-bridge
删除网络
docker network rm my-bridge
容器与网络的关系
准备环境
讲之前,先准备一套干净的docker主机环境(如果有了就跳过此步骤),使用VMware克隆一台虚拟主机,在关闭的状态下,按照下边步骤更改mac地址,否则复制的主机ip跟被复制的主机ip一样,确定之后,启动新克隆的主机即可。
docker rmi -f $(docker ps -aq)
docker rmi -f $(docker images -aq)
如果有swarm相关的设置,先离开集群,再删除自动创建的docker_gwbridge网络。
最终查看变成这样既可:
正文讲解
上边讲了docker的基本网络知识,众所周知,用docker还是要用容器的,那么容器跟docker的关系到底是什么样的呢?你应该有这样的疑问:每个docker容器都是一个独立的linux主机,那么这些独立的容器是怎么跟docker主机联通的?容器跟容器又是为什么能互相访问?不同网络下的容器怎么互相访问,原理是什么?又该怎么实现跨主机的容器访问?跨主机实现联通的原理是什么呢?
把这些问题搞清楚了,docker的网络知识基本也能有大致的了解了,先不要想着很难,其实等你了解了,你会发现真的很简单,就像解密魔术一样,下边我们来针对每个问题进行解密,也来一步步摸清楚里边的套路。
问题一:容器是怎么跟docker主机联通的?
首先我们来运行一个容器,以nginx为例:
docker run -d --name nginx01 -p 80:80 nginx
暂停一下,先安装几个工具,以便我们更好的查看网络情况,首先在主机上安装bridge-utils,方便查看设备和网卡的关系:
yum install bridge-utils -y
在容器中安装查看ip的命令和ping命令
apt-get update
apt-get install inetutils-ping -y
apt-get install net-tools -y
继续!!!
首先,我们在容器内部连接一下主机
docker exec -it nginx01 ping 192.168.150.133
可以联通,再用主机连接一下容器
#进入容器内部
docker exec -it nginx01 /bin/bash
ifconfig
退出返回主机
ping 172.17.0.2
没问题,依然能ping通,原因在哪呢,下边我们再用ip a看一下主机网络:
发现多了多了一个veth网卡。
在查看一下网卡详情,执行下边的命令:
brctl show
可以看到在docker0下挂着一个网卡,由此可见docker0创建了一对网卡,就像veth pair技术一样,让主机能够跟容器内部进行通信。
问题二:容器之间为什么能互相访问?
我们再运行一个nginx容器
docker run -d --name nginx02 -p 81:80 nginx
创建完成之后,会发现主机网络下,又多了一个网卡
docker0下也关联了两个网卡
同时,容器也可以互相ping通
原理:
这种网络连接方法我们称之为Bridge网桥模式,bridge也是docker中默认的网络模式,这个我们在文章开始也讲过。
如果你还有疑问,那么再执行一个命令,你就会明白了:
#查看bridge网络详情
docker network inspect bridge
这里显示的就是docker中所有容器的网络详情,这些容器都是默认使用bridge进行桥接。
容器中是可以访问互联网的,也是docker主机网络通过NAT进行转换的,NAT是通过iptables实现的。
问题三:不同网络下的容器互相访问及原理
首先我们来创建自定义网络
docker network create nginx-net --subnet=172.18.0.0/24
再运行一个新的nginx指定自定义网络
docker run -d --name custom-net-nginx --network nginx-net nginx
查看自定义网络详情,可以看到网络下关联着刚创建的容器
现在用默认网络下的nginx01 ping 自定义网络下的 custom-net-nginx(172.18.0.2)
docker exec -it nginx01 ping 172.18.0.2
显然是不通的,根本就不在一个网段下。
那么及指定nginx01到自定义网络下,命令如下:
docker network connect nginx-net nginx01
再次ping,发现可以ping通了:
并且还可直接通过别名ping
docker network inspect nginx-net
注意:通过别名ping只有自定义网络可以,默认的网络不行
原因:
官方解释:默认桥接网络bridge存在缺陷,不建议在生产环境中使用,只能通过 IP 地址进行通信,除非它们使用 legacy–link标志链接,但是–link也即将过时,不推荐使用。
用户定义的网桥提供容器之间的自动 DNS 解析。
下边是官方解释截图:
好啦,言归正传,那为什么connect之后,两个网络下的容器就能联通了,那么下边我们查看一下自定义网络详情就明白了:
当执行connect命令之后,docker会默认在自定义网络下创建容器连接,也就是说此时的nginx01同时拥有两个网段,进入nginx01容器内部你就会看到:
问题四:跨主机容器之间互相访问的方法和原理?
在我们使用docker swarm的时候,我们会发现,swarm集群建立之后,各节点主机上的容器之间也能互相访问。
创建swarm集群之后,会默认创建两个网络bridge和overlay网络:
对应容器中也会看见有两个网段,分别对应bridge和overlay。
overlay的网络就是实现docker多主机的分布式网络,能够实践容器多机通信也是因为它,具体原理可能就是类似 veth pair吧,详情请自行研究。
总结
其实从上边这么多的案例和讲解,也不难看出来,实现容器之间的通信原理就是建立网络,关联容器,让容器处在一个网段下即可,话虽简单,但需要理解透彻才能牢记。
其实容器内部也是能访问外网的,我们也可以在内部直接通过外网访问其他容器或者其他节点容器,但是内网更快,更省流量,这就是差别,也是追求的不同。