为什么不同命名空间的docker容器可以相互通信?
一、什么是容器网络栈
所谓容器能看见的“网络栈”,被隔离在自己的Network Namespace当中
- 网卡(network interface)
- 回环设备(loopback device)
- 路由表(Routing Table)
- iptables规则
当然 ,容器可以直接声明使用宿主机的网络栈:-net=host(不开启Network Namespace),这样可以为容器提供良好的网络性能,但是也引入了共享网络资源的问题,比如端口冲突。
大多数情况下,我们希望容器能使用自己的网络栈,拥有属于自己的IP和端口
二、容器如何和其他不同Network Namespace的容器交互 ?
- 将容器看做一台主机,两台主机通信直接的办法,就是用一根网线连接,如果是多台主机之间通信,就需要用网络将它们连接到一台交换机上
- 在linux中,能够起到虚拟交换机作用的设备是网桥(Bridge)
网桥是一个工作在数据链路层的设备,功能是根据MAC地址学习来将数据包转发到网桥不同端口上,为了实现上述上的,Docker项目默认在宿主机上创建了一个docker0的网桥,连接在上面的容器,可以通过它来通信
三、如何把容器连接到docker0网络上
需要一种叫Veth Pair的虚拟设备。当Veth Pair被创建出来后,总是以两张虚拟网卡(Veth Peer)的形式成对出现 ,而且从其中一个网卡出的数据包,可以直接出现在它对应的另一张网卡上,即使两张卡在不同的Network Namespace里
这就使Veth Pair常常被用作连接不同的Network Namspace的网线
四、示例演示
下面将在宿主机启动两个容器,分别是nginx-1和nginx-2演示,nginx-1容器访问nginx-2是如何通信的
1. 运行一个nginx-1容器
docker run -d --name=nginx-1 nginx
2.查看nginx-1的网络设备
root@d5bfaab9222e:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.18.0.2 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:ac:12:00:02 txqueuelen 0 (Ethernet)
RX packets 3520 bytes 8701343 (8.2 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3010 bytes 210777 (205.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0的网卡,是Veth Pari设备的其中一端
3.查看nginx-1的路由表,通过route命令查看
root@d5bfaab9222e:/# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 172.18.0.1 0.0.0.0 UG 0 0 0 eth0
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
所有172.18.0.0/16网段的请求,都交给eth0处理,这是Veth Pair设备的一端,另一端在宿主机上
4.查看宿主机的网桥
通过brctl show查看
root@VM-0-8-ubuntu:/home/ubuntu# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242c635ddb8 no veth4d1c130
可以看到,docker0上插入上veth4d1c130网卡
5.再运行一个nginx-2
docker run -d --name=nginx-2 nginx
6.再查看宿主机网桥
root@VM-0-8-ubuntu:/home/ubuntu# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242c635ddb8 no veth4d1c130
vetha9356e9
可以看到,docker0插上了两张网卡veth4d1c130、 vetha9356e9
此时,当容器nginx-1(172.18.0.2)ping容器nginx-2(172.18.0.3)的时候,就会发现两个容器是可以连通的
五、nginx-1能访问nginx-2的原理是什么?
被限制在Network Namespace的容器进程,是通过Veth Pair设备+宿主机网桥的方式,实现跟其它容器的数据交换
1.nginx-1访问nginx-2时,IP地址会匹配到nginx-1容器的每二条路由规则
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
凡是匹配这条规则 的IP包,应该经过本机的eth0网卡,通过二层网络发往目的主机
2.要通过二层网络到达nginx-2 ,需要有172.18.0.3的MAC地址,找到
nginx-1容器需要通过eth0网卡发送一个ARP广播,通过IP来查看对应的MAC地址
这个eth0网卡,是一个Veth Pair,它的一端在nginx-1容器的Network Namespace,另一端位于宿主机上(Host Namespace),并且插入在了宿主机的docker0网桥上
一旦虚假网卡(veth4d1c130)被插在网桥(docker0)上,调用网络的数据包会被转发给对应的网桥,所以ARC请求会被发给docker0
3.docker0转发数据到到相应的nginx-2
docker0会继续扮演二层交换机的角色,根据数据包的上的MAC地址(nginx-2的MAC地址),在它的CAM表里查对应的端口,会找到vetha9356e9,然后将数据包发往这个端口,这样数据包就到了nginx-2容器的Network Namespace里
nginx-2看到它自己的eth0网卡上出现了流入的数据包,然后对请求进行处理,再返回响应给nginx-1
可以打开iptables的TRACE功能查看数据包的传输过程,通过tail -f /var/log/syslog
# iptables -t raw -A OUTPUT -p icmp -j TRACE
# iptables -t raw -A PREROUTING -p icmp -j TRACE
原理图如下

为什么不同命名空间的docker容器可以相互通信?的更多相关文章
- Docker容器跨主机通信之:直接路由方式
一.Docker网络基本原理 直观上看,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)与外界相通,并可以收发数据包:此外,如果不同子网之间要进行通信,需要额外的路由机制. Docker ...
- Docker容器跨主机通信
默认情况下Docker容器需要跨主机通信两个主机节点都需要在同一个网段下,这时只要两个Docker容器的宿主机能相互通信并且该容器使用net网络模式,改实现方式为网桥模式通信: 除此之外我们还可以通过 ...
- docker容器内外相互拷贝数据
从宿主机上拷贝文件到容器内 注意:一下红色字体为宿主机文件 docker cp 文件 容器名:目录 # docker cp httpd-2.4.34.tar.gz node4:/opt/ 从宿主机上拷 ...
- Docker容器跨主机通信--overlay网络
一.Docker主机间容器通信的解决方案 Docker网络驱动 Overlay: 基于VXLAN封装实现Docker原生Overlay网络 Macvlan: Docker主机网卡接口逻辑上分为多个子接 ...
- Docker容器跨主机通信之:OVS+GRE
一.概述 由于docker自身还未支持跨主机容器通信,需要借助docker网络开源解决方案 OVS OpenVSwich即开放式虚拟交换机实现,简称OVS,OVS在云计算领域应用广泛,值得我们去学习使 ...
- docker容器之间的通信
容器之间互通 新建两个容器 docker run -d --name box1 busybox /bin/sh -c "while true;do sleep 3600;done" ...
- docker images之间相互通信 link
同一个host上的两个container 首先启动一个nginx. container起名叫netease_nginx docker run --detach --name netease_nginx ...
- Docker: Docker容器之间互相通信
最简单的方法,关闭防火墙(只建议用于开发环境) systemctl stop firewalld
- Docker容器学习梳理 - 容器间网络通信设置(Pipework和Open vSwitch)
自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求.容器的网络通信又可以分为两大方面:单主机容器上的相互通信,和跨主机的容器相互通信.下面将分别针对这两方面,对容 ...
随机推荐
- [币严区块链]ETH搭建节点区块数据同步的三种模式:full、fast、light
ETH 全节点Archive(归档)模式数据量增长图 上述图表可通过链接查看:https://etherscan.io/chartsync/chainarchive 通过上表,可以看到截止2019年 ...
- jvm内存溢出问题的定位方法
jvm内存溢出问题的定位方法 今天给大家带来JVM体验之内存溢出问题的定位方法. 废话不多说直接开始: 一.Java堆溢出 测试代码如下: import java.util.*; public cla ...
- 浅谈DanmakuView
今天简单介绍一下开源的弹幕引擎---danmakuView 使用之前在build.gradle里面添加下面这一条(目前我使用的工具是AndroidStudio 3.1.2) impleme ...
- git windows 安装 - Github同步 / Vscode源代码管理:Git 安装操作
github上创建立一个项目 登录github网站,在github首页,点击页面右下角"New Repository" 最后点击"Create Repository&qu ...
- SQL手工注入进阶篇
0.前言 上一篇我们介绍了SQL手工注入的流程以及步骤,但在实际的安全问题以及CTF题目中,查询语句多种多样,而且是肯定会对用户的输入进行一个安全过滤的,而这些过滤并不一定是百分百安全的,如何利用一些 ...
- Nginx缓存原理及机制
文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 上篇文章介绍了Nginx一个较为重要的知识点:Nginx实现接口限流.本篇文章将介绍Nginx另一个重要知识点 ...
- Java门面模式
一.简介 隐藏系统的复杂性,对外提供统一的访问入口,外部系统访问只通过此暴露出的统一接口访问.是一种结构型模式.封装子系统接口的复杂性,提供统一的对外接口,能够使子系统更加简单的被使用. 二.结构及使 ...
- 【深度学习】Focal Loss 与 GHM——解决样本不平衡问题
Focal Loss 与 GHM Focal Loss Focal Loss 的提出主要是为了解决难易样本数量不平衡(注意:这有别于正负样本数量不均衡问题)问题.下面以目标检测应用场景来说明. 一些 ...
- CocosCreator实现动物同化
获取源码 关注微信公众号『一枚小工 』,发送『动物同化 』获取完整游戏源码. 游戏玩法 游戏目标是将游戏区域的动物全部同化成同一种动物.游戏从左上角开始,从右边点击需要变成的目标动物头像,如果被同化动 ...
- python爬虫入门新手向实战 - 爬取猫眼电影Top100排行榜
本次主要爬取Top100电影榜单的电影名.主演和上映时间, 同时保存为excel表个形式, 其他相似榜单也都可以依葫芦画瓢 首先打开要爬取的网址https://maoyan.com/board/4, ...