陶刚的博客
与你分享我的点滴

Docker Network(一)

说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!

一、概述

1.单机和多机

在这里插入图片描述

2.环境搭建

说明:需要两台装有docker的linux(centos7)机器,之前博主在Docker Playground的使用(2020实操图解)中有详细说明安装方式:第一种是通过VirtualBox或者VMware虚拟化软件直接创建Linux虚拟机,在虚拟机里安装使用Docker;第二种是通过Vagrant + VirtualBox快速搭建Docker Host(推荐使用);第三种是通过Docker-Machine快速搭建Docker Host,博主这里是采用第一种VMware虚拟化软件直接创建Linux虚拟机,并在虚拟机中安装了docker

现在博主给大家演示一下第二种推荐方式Vagrant + VirtualBox快速搭建两台安装docker的centos7机器

2.1 配置Vagrantfile

  • 首先初始化Vagrantfile文件
    在这里插入图片描述
  • 在Vagrantfile文件中,进入如下配置
    在这里插入图片描述
  • 在centos7目录下创建setup.sh文件,文件内容如下,就是在搭建好的centos7机器中执行的命令
    在这里插入图片描述

2.2 快速搭建两台centos7

  • 为了节约时间,提前在vagrant官网下载好了centos7的virtualbox.box镜像文件,将其拷贝到centos7目录下,设置添加本地box镜像文件
    在这里插入图片描述
  • 一切准备就绪,执行vagrant up命令即可,过程时间比较长
    在这里插入图片描述
  • 搭建完成,查看virtualbox,显示搭建的docker-node1和docker-node2两天centos7正在运行
    在这里插入图片描述
  • 通过vagrant命令查看虚拟机状态,显示正在运行
    在这里插入图片描述
  • 进入docke-node1虚拟机中,查看ip地址与vagrantfile中设定的一致
    在这里插入图片描述
  • 进入docke-node2虚拟机中,查看ip地址与vagrantfile中设定的一致
    在这里插入图片描述
  • 以上方式是为了给大家进程操作演示,前面也说了博主是使用VMware来搭建两台安装docker的centos7虚拟机,除了这两种方式还可以通过docker-machine来create创建安装docker的linux虚拟机或者是直接使用mac或windows本机上的docker,但是这种方式不建议,推荐以上Vagrant + VirtualBox方式或者是跟博主一样使用VMware开启两台装有docker的linux虚拟机(前提你的电脑配置玩得转),下面则是博主使用虚拟工具VMware搭建装有docker的centos7虚拟机
    在这里插入图片描述
    在这里插入图片描述

3.网络基础

3.1 网络分层的概念

网络层次可划分为五层因特网协议栈和七层因特网协议栈,具体可以参考百度百科
在这里插入图片描述

3.2 路由的概念

路由(routing)是指分组从源到目的地时,决定端到端路径的网络范围的进程,具体可以参考百度百科
在这里插入图片描述

3.3 IP地址和路由

在这里插入图片描述

3.3 公有IP和私有IP

在这里插入图片描述

3.4 网络地址转换NAT

在这里插入图片描述

3.5 ping和telnet

ping: 验证IP的可达性

  • 分别ping以下两个IP,一个能ping通丢包率为0,一个不能ping通丢包率为100%
    在这里插入图片描述

telnet: 验证服务的可用性

  • 分别telnet同一IP不同端口,一个成功,另一个不成功
    在这里插入图片描述
  • 有时候会出现一些网站不能ping通但是一样可以正常访问,那么这种情况就要使用telnet来验证服务的可用性了
    在这里插入图片描述

二、Linux Network Namespace

1.Container Network Namespace

  • 首先直接拉取一个busybox镜像,这个镜像是基于linux的,非常小的
    在这里插入图片描述
  • 然后通过后台运行busybox容器,并在容器中执行一个无限循环shell命令
    在这里插入图片描述
  • 紧接着通过exec交互式进入到容器中执行/bin/sh命令,查看该容器中的网络接口,一共有两个分别是lo(local)和eth(网卡),这个就是网络的Namespace(命名空间)
    在这里插入图片描述
  • 退出容器,在本地centos7机器上查看网络接口,可以发现有很多个网络接口,对比容器中的Network Namespace是隔离开的,通过linux network namespace实现了容器和本机网络的隔离
    在这里插入图片描述
  • 同理再次创建一个容器,查看网络也是隔离开的
    在这里插入图片描述
  • 这两台容器,都是可以互相ping通的,那么说明两个独立的network namespace是可以互相ping通的
    在这里插入图片描述

2.Create && Delete Network Namespace

  • 查看本机已有的network namespace
sudo ip netns list
  • 创建一个名为test1的network namespace
sudo ip netns add test1
  • 删除名为test1的network namespace
sudo ip netns delete test1

在这里插入图片描述

  • 创建test1和test2两个网络命名空间,并查看网络接口,发现只有lo接口,并且状态为DOWN停止
sudo ip netns exec test1 ip a
sudo ip netns exec test2 ip a

在这里插入图片描述

  • 还可以通过ip link来查看本机和两个创建好的network namespace网络接口
sudo ip netns exec test1 ip link
sudo ip netns exec test2 ip link

在这里插入图片描述

3.Network Namespace + veth-pair

说明: 目前创建好的两个network namespace为test1和test2,这两个网络命名空间分别都有一个本地回环口lo,并且状态为DOWN停止,现在需要将这两个回环口lo的状态修改为up,并且使这两个网络命名空间进行相连,那么要想这两个namespace相连则需要创建veth-pair(一对虚拟设备接口),将这一对虚拟设备接口分别放一个在test1和test2中,那么这样就能实现两个网络命名空间相连

在这里插入图片描述

  • 首先设置test1的状态为up,但是设置后发现为UNKNOWN,之所以UP不起来是这个接口是需要两端进行连接的,就好比虚拟机linux eth33要与本机windows的虚拟化端口进行连接一样的道理,也就是说单个端口是无法UP起来的必须是一对
sudo ip netns exec test1 ip link set dev lo up

在这里插入图片描述

  • 现在则需要去创建一对veth-pair设备接口,分别是veth-test1和veth-test2,对比创建之前和创建之后,linux本机上的ip link
sudo ip link add veth-test1 type veth peer name veth-test2

在这里插入图片描述

  • 现在将veth-test1接口添加到namespace test1里面去,然后查看test1 这个namespace显示添加veth-test1接口成功,并且linux本机上的veth-test1接口不见了
sudo ip link set veth-test1 netns test1

在这里插入图片描述

  • 同理将veth-test2接口添加到namespace test2里面
sudo ip link set veth-test2 netns test2

在这里插入图片描述

  • 查看test1和test2两个namespace的以上添加的接口,状态都是DOWN,并且没有IP地址
sudo ip netns exec test1 ip link
sudo ip netns exec test2 ip link

在这里插入图片描述

  • 即所以为这两个端口添加IP地址,再次查看test1和test2的ip link发现状态还是DOWN(说明博主这里之前IP设置有问题,所以删除重头来过,导致这里添加的端口索引从6,7变成了8,9
sudo ip netns exec test1 ip addr add 192.168.88.1/24 dev veth-test1
sudo ip netns exec test2 ip addr add 192.168.88.2/24 dev veth-test2

在这里插入图片描述

  • 那么当设置完namespace ip后,则需要设置namespace 状态为UP
sudo ip netns exec test1 ip link set dev veth-test1 up
sudo ip netns exec test2 ip link set dev veth-test2 up

在这里插入图片描述

  • 此时,查看test1 和 test2 namespace的ip地址,就是我们当初设置的ip
sudo ip netns exec test1 ip a
sudo ip netns exec test2 ip a

在这里插入图片描述

  • 在test1 namespace中ping test2 namespace 端口IP 以及在test2 namespace中ping test1 namespace 端口IP ,都是可以互相ping通的
sudo ip netns exec test1 ping 192.168.88.2
sudo ip netns exec test2 ping 192.168.88.1

在这里插入图片描述

三、Docker Bridge Network

说明:在上面目录二中博主是通过创建veth-pair一对接口来让两个namespace进行互相连接的,那么现在就来看看docker container是怎么进行连接的,不明白的可以参阅官方文档

1.验证Container连接

  • 之前博主创建了两个基于busybox image名为test1和test2的容器,因为博主关机过,所以这里需要重启启动这两个容器
    在这里插入图片描述
  • 查看test1和test2容器的IP地址,那么这两个容器肯定是能互相ping通的
    在这里插入图片描述

2.Bridge Network

2.1 查看bridge网络数据

  • 为了查看效果,博主将运行的test2 容器进行删除,然后来查看本地centos的网络信息
sudo docker network ls

在这里插入图片描述

  • 查看本地linux bridge网络,可以发现docker这个test1容器是连接在bridge网络上的,在containers键中显示出包含的docker容器信息
sudo docker network inspect <network id/name>

在这里插入图片描述

  • 查看linux本机的网络接口以及test1 容器的网络接口,其中基于busybox image创建的容器本身是有一个自己的network namespace的,与本机docker0(docker0的network namespace就是本机centos机器)这个bridge网络也是通过veth-pair(也就是vethe125f42@if10和eth0@if11)来进行连接test1这个容器的network namespace
    在这里插入图片描述

2.2 验证container通过veth连接到docker0

  • 通过brctl工具来查询网桥信息,可以发现docker0这个bridge的interface接口为本机linux机器的vethe125f42,也就是说这个接口是连接到linux bridge上的
sudo yum install bridge-utils
brctl show

在这里插入图片描述

  • 因为之前博主删除了test2容器,现在再次进行创建
sudo docker run -d --name test2 busybox /bin/sh -c "while true; do sleep 3000; done;"

在这里插入图片描述

  • 此时验证是否添加到linux bridge网络中
sudo docker network inspect bridge

在这里插入图片描述

  • 查看docker0这个bridge多了一个interface接口vethfdba8dd指向了本机的接口vethfdba8dd@if16形成了一对veth-pair来让test2容器的network namespace与本机docker0 network namespace进行相连接
    在这里插入图片描述
  • 关于以上test1、test2容器的network namespace与本机docker0 network namespace是通过一对veth-pair进行相连的,架构图如下,就相当于在自己家里有两台设备同时连接到一台路由器上或者交换机上,即使没有连接外网,这两台设备也是可以通过局域网进行互相通信的
    在这里插入图片描述

2.3 container连接到外网

  • 首先容器能够连接到外网,肯定是本机linux机器能够连接到外网才行,本机比如是通过eth0端口来进行外网访问,那么容器是可以通过连接到docker0 这个bridge做一个NAT网络地址转换成eth0端口,那么就可以作为linux主机的数据包发送到internate了,即就可以访问外网了
    在这里插入图片描述

四、Container Link && Create Custom Bridge

说明: 有这么一个需求场景,后台项目需要访问数据库mysql,那么就需要这个数据库的地址以及端口号(固定的),创建两个容器
一个容器是运行数据库服务,另一个容器是运行后台服务,这个后台服务是需要去访问数据库,那么通过docker inspect <container id/name>来查看运行数据库服务的容器ip,运行后台服务的容器将数据库服务的容器ip传进去作为数据库参数,这样才能连接到数据库容器里面,但是这种方式是不可取的,因为在写代码时,根本不知道数据库容器的ip是多少,那么可以通过在创建数据库容器时给这个容器取一个名字,如果通过这个名字可以直接访问数据库容器,那么就不需要通过ip来进行访问了,实现方式这是通过docker link机制,在创建第二个容器时候,可以把它link到第一个容器上面,这样访问第一个容器时候,就可以直接通过name进行访问了

1.通过创建link的方式ping通容器name

  • 首先先进入到test2这个容器中,通过ping test1容器的ip是可以ping通的,但是ping test1这个name是无法ping通的
    在这里插入图片描述
  • 现在删除test2容器,然后重新创建test2容器并将其link到test1上面,ping test1就可以ping通了,那么直接通过test1:3306就可以访问数据库了
    在这里插入图片描述

2.通过创建bridge的方式ping通容器name

  • 删除test2容器,重新创建最初的test2,不使用link
sudo docker run -d --name test2 busybox /bin/sh -c "while true; do sleep 3000; done;"

在这里插入图片描述

  • 查看目前本机的network,然后创建一个bridge driver 名我my-bridge
sudo docker network create -d bridge my-bridge

在这里插入图片描述

  • 创建bridge成功后,通过brctl show命令来查看本机的网桥信息,其bridge name的后面字段则是这个bridge对应的network id,需要注意的是目前这个bridge name为f1ccd24e9751的网桥并没有interface接口,原因还没有让容器使用我们创建的bridge
sudo docker network ls
brctl show

在这里插入图片描述

  • 创建一个名为test3并不使用默认docker0这个bridge而是使用我们自己创建的my-bridge的容器
sudo docker run -d --name test3 --network my-bridge busybox /bin/sh -c "while true; do sleep 3000; done;"

在这里插入图片描述

  • 再次查看网桥信息,我们创建的网桥则就有test3这个容器的接口了
ip link
brctl show

在这里插入图片描述

  • 查看创建的my-bridge的元数据,可以看到容器test3已经连接到这个bridge上了
sudo docker network inspect my-bridge

在这里插入图片描述

  • 对于之前已经创建好的test1和test2容器,还是可以将其link到我们新建的my-bridge上,可以直接输入sudo docker network回车就能出现其命令帮助,connect命令可以将指定的容器连接到指定network上
sudo docker network
sudo docker network --help

在这里插入图片描述

  • 将test2连接到my-bridge上,并查看my-bridge元数据,显示test2容器连接成功
sudo docker network connect my-bridge test2
sudo docker network inspect my-bridge

在这里插入图片描述

  • 因为之前创建test1和test2容器时,已经默认将其连接到bridge上了,现在又将test容器设置连接到创建的bridge上面,所以查看bridge元数据,结果发现test2也在这个bridge上面,所以test2这个容器即属于默认的bridge又属于我们创建的my-bridge
sudo docker network inspect bridge

在这里插入图片描述

  • 现在分别进入test2和test3 /bin/sh中,分别ping test3和test2容器的IP都是可以ping通的,但是居然无法通过容器name ping通,这就很奇怪了,因为dokcer官网上说的是将两个容器添加到自定义创建的bridge后,容器之间是可以通过name进行访问的
sudo docker exec -it test3 /bin/sh
sudo docker exec -it test2 /bin/sh

在这里插入图片描述

  • 导致以上连接到自己创建的bridge上两个容器test2和test3不能互相通过容器name ping通的原因,博主猜想是因为image原因,所以博主这里重新换个centos最新版本镜像进行尝试,博主在之前文章中已经安装过centos镜像了,所以可以直接通过image创建容器,删除所有容器以及删除创建的my-bridge
sudo docker network rm my-bridge

在这里插入图片描述

  • 执行如下命令,也就是重复之前操作,但是这次是创建的容器是基于centos
docker run -d --name test1 centos /bin/sh -c "while true; do sleep 3000; done"
docker run -d --name test2 centos /bin/sh -c "while true; do sleep 3000; done"
sudo docker network create -d bridge my-bridge
docker run -d --name test3 --network my-bridge centos /bin/sh -c "while true; do sleep 3000; done"
sudo docker network connect my-bridge test2

在这里插入图片描述

  • 查看my-bridge元数据,验证test2和test3容器连接到此bridge
sudo docker network inspect my-bridge

在这里插入图片描述

  • 现在进入test3和test2容器shell里面,互相ping对方容器的ip以及name,证明通过容器name进行ping通的,之前博主猜想busybox镜像导致的是正确的
sudo docker exec -it test3 /bin/sh
sudo docker exec -it test2 /bin/sh

在这里插入图片描述

  • 现在将test1容器连接到my-bridge中,来验证三台容器都能通过name互相ping 通
sudo docker network connect my-bridge test1

在这里插入图片描述

  • 分别进入test1、test2、test3 容器shell中互相通过容器name都是能ping通的,原因是test1、test2以及test3这两个容器都连接到我们创建的my-bridge中,所以才能够互相ping通的
sudo docker exec -it test3 /bin/sh
sudo docker exec -it test2 /bin/sh
sudo docker exec -it test1 /bin/sh

在这里插入图片描述

赞(1) 打赏
版权声明:本文为CSDN博主「cdtaogang」的原创文章,遵循CC 4.0 BY-NC-SA版权协议,转载请附上原文出处链接及本声明:记录学习生活 » Docker Network(一)

评论 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏