乐趣区

关于docker:菜农升职记之-Docker网络

大家好呀,我是小菜~

本文次要介绍 docker 网络

微信公众号已开启,小菜良记,没关注的同学们记得关注哦!

刚完结完一个需要的小菜农刚想关上公众号《菜农曰》看看博客划划水,叮叮又响了!

“小菜农,这个测试环境的服务器连贯信息,你登上去通过 docker 部署下你刚刚提交的分支测试下哈!”

导师程立给小菜农发来了音讯

“docker 是个啥玩意?之前不都是间接在服务器找个目录上传而后 nohup java -jar ... & 一套组合拳下来吗?”

小菜农登时又自闭了,自从来到了职场真是处处碰壁!想想在学校还是三好学生真是唏嘘不已!

“等等!我记得公众号《菜农曰》写了一篇对于 docker 的,连忙翻出来看看”

Docker 上手,看完感觉本人又行了!

许久之后,小菜农方从文章中回过神来,“这下不得拿捏了!”。他关上服务器输出 docker ps 试了下指令

“有点意思啊!”他依照文章中的教程开始部署本人的利用我的项目。先是编写了本人利用的 dockerfile,而后通过 docker build 构建出本人的镜像,最初执行 docker run来运行本人的镜像,一整套下来零打碎敲,行云流水!而后便在浏览器测试了下本人的性能内容,测试通过后。小菜农便陷入了思考,docker 是一个容器,能够内嵌一个操作系统,每个容器之间是互相隔离的,那为啥我能够从外界拜访容器内的内容?容器之间是如何通信的?又怎么创立自定义网络?

几个问题想的小菜农头都大了!放弃是不可能放弃的,没准这当前能够成为本人升职加薪,走上人生巅峰的垫脚石之一呢!从这里能够看出小菜农还是很有斗志的嘛~

docker 容器在装置的时候会主动在 host 上创立三个网络,小菜农看到了这句话,那要怎么查看这三个网络了,通过 help 指令看看会不会有所发现?他疾速地在终端敲入docker --help

“哦豁,果然有!network 不就是我想要的吗!”。机智的小菜农开始顺藤摸瓜,继而敲入docker network --help

ls 能够查看 docker 的网络,那我来试试”

终端上正如小菜农所料,呈现了他想要看的内容。“bridge、host、none?”小菜农还是有些网络根底的,前两个看名称都有点相熟,然而 none 是个啥玩意?什么都没有的网络吗?。小菜农通过一番查问,没想到还真是,不由得拜服命名的开发者,这可真让人顾名思义~ 查问发现,挂在这个网络下的容器除了 lo,没有任何网卡

咱们启动容器是通过 docker run来执行的,这个指令前面咱们能够附加参数,通过 --network = none就能够指定该容器是应用 none 网络~

“那么这样一个关闭的网络有啥用,都上不了网”,小菜农嘀咕道

没错,就是要 上不了网,有些非凡的利用场景须要将网络关闭起来,往往这种场景意味着安全性要求很高,因而须要进行隔离,这种状况就能够放到 none 网络避免被人侵入。

“既然是非凡场景才须要,那我目前应该还接触不到非凡场景,pass pass!让我康康 host 是什么网络”

小菜农晓得了能够通过 --network指定网络类型,他试着启动了一个网络类型为 host 的 nginx 来查看

小菜农看到这个网络配置不禁陷入了深思,这怎么似曾类似?他将终端命令行往上滚了几页,终于发现为啥眼生了!

原来他在下面的时候已经输出 ip l 查看了宿主机的网络,你能够发现这两个配置是截然不同的!那就阐明连贯到 host 网络的容器共享 Docker host 的网络栈,容器的网络配置与宿主机的配置齐全一样。那这样子的话间接应用 Docker host 网络的最大益处就是 性能 了。如果容器对网络传输效率有较高要求的时候,就能够应用 host 网络,也相当于是应用宿主机的网络,那么这样做的缺点是什么?那就是 端口会抵触,在宿主机上曾经应用的网络,容器就不能再应用了!

小菜农感觉应该没那么简略,又查了下 host 网络的应用场景,不一会就有所发现了,应用 host 网络的另一个用处就是 能够让容器间接配置 host 网络,比方某些须要跨 host 的网络解决方案,其自身也是以容器的形式运行的,这些计划须要对网络进行配置,比方治理 iptables 之类的场景。

“真是丈母娘看郎,越看越爱~”小菜农曾经有点迷上了 docker,越深刻才发现越有意思。“还剩下 bridge 网络类型,让我康康!”

bridge 是一种桥接模式的网络,桥接顾名思义就是一端在这里另一端在那里。小菜农又大胆猜想了,那必定就是一端在容器上,一端在宿主机上!接下来便进行了验证

小菜农想起了一个命令 brctl,该命令brctl 可用于设置、保护和查看 linux 内核中的以太网网桥配置。

无奈应用 brctl 命令的童鞋能够应用以下命令装置

yum install -y bridge-utils

他通过 brctl show 查看宿主机的网桥配置,发现有个命为 docker0 的网桥,而后他通过启动一个容器持续察看网桥变动:

小菜农发现 interface 的内容产生了变动!有一个新的网络接口 veth9b75794 挂在了 docker 0 上,而 veth9b75794 就是刚刚创立容器的网卡,小菜农紧接着查看了下刚创立容器的网络配置

容器中有个一个 eth0@if67 网卡,小菜农会心一笑

“嘿嘿,被我发现了吧,要不是我会点网络,还真被这忽悠住了。刚刚下面查看到的网络接口是 veth9b75794,而这里是 eth0@if67,换成刚接粗网络的童鞋必定一头雾水,这两个怎么不一样!实际上 eth0@if67veth9b75794 是一对 veth pairveth pair 是一种成对呈现的非凡网络配置,而这就是我下面猜想的那样,网桥就是能够把它们设想成由一根虚构网线连接起来的一对网卡,网卡的一头(eth0@if67)在容器中,另一头(veth9b75794)挂在网桥 docker0 上,其成果就是将 eth0@if67 也挂在了 docker0 上

172.17.0.2/16 这个 IP 也就是宿主机配置的,小菜农查看了下 docker 的 bridge 配置

发现有个 bridge 网络配置的 subnet 就是 172.17.0.0/16,并且网关是 172.17.0.1。那么这个网关就是 docker 0!小菜农在宿主机输出 ifconfig' 进行验证

而这时,小菜农的脑子里浮现了一张图

到这里,小菜农曾经相熟了 docker 的三种网络类型的状况,便开始思考如何能够自定义网络,必定存在很多场景用户须要依据业务来创立自定义网络来满足需要。在下面小菜农想要查问 docker 的网络配置时有输出过命令 docker network --help,输入后果的时候小菜农有点印象其中如同有个 create 的命令,连忙又输出一遍进行确认:

果然,docker 曾经反对用户创立自定义网络。很快呀!小菜农便在终端输出了创立网络的命令:

眼尖的小菜农一眼就发现了不对劲,创立网络的时候并没有指定 DRIVER 呀!而这个时候创立进去的网络驱动默认就是 bridge,那就阐明是否还能够创立其余网络驱动的网络?小菜农再一次进行了尝试,但这次后果确认小菜农碰壁了

“难道只能创立 bridge 驱动类型的网络吗?”小菜农嘀咕。仍旧不死心便上了某搜索引擎进行后果查找。查找后发现原来 Docker 提供了三种 user-defined 的网络驱动,别离是 bridgeoverlaymacvlanoverlaymacvlan用于创立跨主机的网络!

“跨主机?那就是集群咯!目前导师调配给我的服务器只有一台,看来没法验证了,只能等后续权限大点再验证了,嘿嘿!”,既然无奈验证其余两种,那就先将 bridge 搞明确~ 小菜农坏笑了起来!

下面曾经创立了一个 bridge 驱动类型的网络,那宿主机的网络配置应该产生了变动,小菜农输出了 brctl show 进行查看:

果然这个时候多了一个名为 br-76c202387b0c 的网桥,通过 ifconfig 能够发现网段也曾经调配了一个:

而这个应该就是新网络的网关了~ 小菜农真是越来越纯熟起来,看来学习真能使人自信!

所有都如小菜农所料,172.18.0.1 就是 Docker 主动调配的 IP 网段

“然而如果自定义的网络多了起来,调配的网段必定也是随之减少,那由 docker 调配的网段必定是随机,不不便记忆,能不能 本人指定 IP 网段”,小菜农突发奇想,输出 docker network create --help 会不会有所发现?

看到这后果,小菜农忍不住笑了起来,真有我的!这 subnetgateway 不就是我想要的吗!~

这不就成了吗!而且宿主机上也有了新的网络,网段为 172.10.0.0/16,网关为 172.10.0.1

既然创立了本人的网络,小菜农登时成就感满满,这不得连忙启动一个容器来试试本人的网络!

能够看到应用本人配置网络启动的容器,调配到的 IP 地址是 172.10.0.2/16,“既然容器的 IP 都是 docker 主动从 subnet 中调配的,那我能不能指定一个动态 IP 呢?”小菜农又提出了疑难,那么只能再祭出老套路 --help 进行解决了!小菜农手脚麻利的敲下 docker run --help | grep 'ip' 查看后果

小菜农笑容逐步变态,没想到本人把握了 help 神器!看来能够通过 --ip xxx来指定本人想要的 IP,敲命令的手法逐步娴熟起来,这不,一会功夫后果就进去了:

到目前为止,小菜农曾经启动了三个容器

而网络之间的拓扑关系也突然而出,小菜农连忙入手画了起来,免得遗记!

小菜农看着图发愣了一会,这图其实曾经挺清晰了,nginx-customnginx-ip 之间必定可能相互连通,小菜农验证一下猜测

后果是对的,那 nginx-default 是否能和其余两个容器相通呢?验证一下就晓得了!

由此可见同一网络中的容器、网关之间是相通的,而属于不同网桥之间的容器是不能相互通信的。难道这样子就完结了吗?两个不同网络之间的容器难道真的不能相通了?小菜农不甘心就这样放弃,盯着屏幕一阵发愣,“有了!加个路由的话,那么两个网络之间应该就能通信了吧!”如果 host 上对每个网络都只有一条路由,同时操作系统上开启了 ip forwarding,那么 host 就会造成一个路由器,挂接在不同网桥上的网络就可能通信!

小菜农通过ip r 查看宿主机上的路由表

能够看到 172.17.0.0/16172.10.0.0/16 两个路由都曾经定义好了,下一步就须要看下 ip forwarding 是否曾经开启,小菜农疾速的敲下指令 sysctl net.ipv4.ip_forward

能够看到 ip forwarding 也曾经开启了。那这个时候只须要为 nginx-default 容器增加一块 c-custom的网卡就能够通信了!万事俱备,只欠东风~

小菜农仍旧通过相熟的配方查看增加网卡的步骤

理解之后便开始入手操作

“nice,没有出错,这下应该能够通信了吧!”小菜农嘀嘀咕咕,缓和的手颤动的心持续敲下 ping 命令进行验证

瞪大了眼,第一次这么有成就感,没想到真的被本人折腾进去了!小菜农冲动的差点站了起来,巴不得大声笑进去,但他晓得,这只是本人成长的第一步,本人曾经胜利的跨出去了!平复下了冲动的心,得出一个本人刚刚试验出的论断

两个容器要能通信,就必须要有属于同一个网络的网卡,当满足这一条件后,容器就能够通过 ip 进行交互了

论断来之不易,小菜农连忙在本人的小本本上记录下来!尝到苦头的小菜农持续在网上进行搜寻,看是否存在其余能够在容器间通信的形式,毕竟用 IP 进行通信还是属于比拟根底的~ 很快,小菜农便找到了答案,有的! 容器间能够通过是那种形式进行通信

  • IP
  • Docker DNS Server
  • joined

IP 通信本人曾经试验过了,接下来就要尝试其余两种形式。Docker DNS Server?看解释是通过 容器名的形式,在下面创立的容器,小菜农都曾经指定了容器名,接下来只有进行试验就行了

果然是能够的!能够通过容器名进行拜访,那就象征这能够不必记忆那么长一串的 IP 了!

前两种形式都曾经试验过了,看到 joined 小菜农又有点懵了,退出? 小菜农持续往下看了解释

joined 容器是另一种实现容器间通信的形式

joined 容器十分特地,它能够使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined 容器之间能够通过 127.0.0.1 间接通信

“还真神奇,docker 中处处充斥了惊喜呀!”,小菜农随后便进行了尝试

这边值得注意的是,两个容器共享同一个网络栈,那么端口就不能抵触,因而启动的时候须要拆散端口

到这里,小菜农不由得称心如意了,刚要退出服务器开始持续工作,却被本人的网页吸引过来了,网页上开着正是小菜农刚刚启动的 docker 我的项目。“咦,外界是怎么与容器进行连贯的?”小菜农再次提出了疑难,容器如何拜访外界?外界又如何拜访容器? 看来还是得持续学习(划水)呀!

小菜农再次切换到服务器页面,尝试从容器内进行拜访外界

其实不必尝试,小菜农也分明,容器必定能拜访到外界,不然内部接口如何调用~ 然而为什么能拜访到呢?小菜农查看了宿主机的 iptables 规定

能够看到有这么两条规定,一条是 docker 0,一条是小菜农刚刚自定义的,那它是什么意思呢?小菜农又犯迷糊了,看了旁边的肖老大,这不有现成的大佬能够问吗!肖老大有些好奇,小菜农这是接到啥需要了,怎么会问到这个问题,不过也没多想,新人总要关照好的不是!便开始巴拉巴拉解释起来,小菜农也听得云里雾里,“这样说明确了吗?”。“啊?哦!差不多晓得这个意思了,嘿嘿,谢谢肖老大”,“不客气不客气,下次遇到不会记得还来找我哈”,肖老大稍微粗暴的嗓门,让小菜农倍感舒适!总结了下肖老大的解释:如果网桥 docker 0 接管到来自 172.17.0.0/16 网段的外出包,就会把它交给 MASQUERADE 解决,而 MASQUERADE 的解决形式就是将包的源地址替换成 host 的地址发送进来,即做了一次网络地址转换 NAT。

既然如此,那么通过抓包应该就可以看分明网络地址转化的过程,小菜农打算应用 tcpdump 来做一次繁难抓包查看下后果,首先他起了两个终端,一个终端通过 ping www.baidu.com 来发送网络包,一个包通过 tcpdump -i docker0 -n icmp 抓取网络信息

172.17.0.2nginx-default 容器的 IP,通过转包能够发现该 IP 地址是往 180.101.49.11 发送数据包,到这里小菜农实现了第一步,承受持续通过 tcpdump -i eth0 -n icmp 查看宿主机的网络流出信息

“啊哈!果然变了,这个时候 ping 包的原地址,变成了 ehp0 的 IP 172.26.19.234

弄清楚了 容器外部拜访外界 后,那么接下来就是搞清楚 外界如果拜访容器

小菜农记得刚刚本人启动容器后,在 PORTS 那里有显示端口,便在浏览器试了下就能够顺利拜访了!小菜农又起了一个容器进行试验

启动容器后,便能够利用 32771 这个端口号进行拜访,而 32771 这个端口是宿主机主动调配的,小菜农又试了下本人指定端口拜访

指定端口后,通过本人指定的端口也是能够拜访的,而这其中的原因,小菜农也通过查问发现是通过 docker-proxy 实现的

每一个映射的端口,host 都会启动一个 docker-proxy 过程来解决拜访容器的流量。

到这里,小菜农就搞懂了 Docker 中的网络应用,然而小菜农眉头一皱,明天玩的都是单机,那么在集群中网络又是如何拜访呢?

不要空谈,不要贪懒,和小菜一起做个 吹着牛 X 做架构 的程序猿吧~ 点个关注做个伴,让小菜不再孤独。咱们下文见!

明天的你多致力一点,今天的你就能少说一句求人的话!

我是小菜,一个和你一起变强的男人。 💋

微信公众号已开启,小菜良记,没关注的同学们记得关注哦!

退出移动版