网站建站业务,python基础教程pdf下载,html5网站开发需要框架吗,德德模板网站建设步骤一、前言 记录时间 [2024-4-16] 系列文章简摘#xff1a; Docker 学习笔记#xff08;六#xff09;#xff1a;挑战容器数据卷技术一文通#xff0c;实战多个 MySQL 数据同步#xff0c;能懂会用#xff0c;初学必备 Docker 学习笔记#xff08;七#xff09;#x…一、前言 记录时间 [2024-4-16] 系列文章简摘 Docker 学习笔记六挑战容器数据卷技术一文通实战多个 MySQL 数据同步能懂会用初学必备 Docker 学习笔记七介绍 Dockerfile 相关知识使用 Dockerfile 构建自己的 centos 镜像 Docker 学习笔记八Dockerfile实战篇制作 Tomcat 镜像发布镜像到 DockerHub 和阿里云
更多 Docker 相关文章请参考上面专栏哦入门篇 1~5 已完结6 开始是精髓篇容器数据卷、Dockerfile、Docker 网络。
本文介绍了 Docker 网络原理介绍了 docker0Veth-pair 技术以及 Docker 给容器分配虚拟网卡的方式。同时讲述了两种容器互联的方式分别是 Link 和 自定义网络。还有容器之间跨网络连通的方式。 二、划重点
当我们在 Linux 宿主机中安装了 Docker
宿主机中就会配置 docker0 网卡docker0 使用的是 Linux 桥接模式使用的技术是 Veth-pair 技术。每启动一个 Docker 容器Docker 就会给该容器分配一个 ip一对虚拟网卡。
关于 Docker0 的结论
Docker 容器 tomcat01 和 tomcat02二者共用一个路由器即 docker0所有容器在不指定网络的情况下都使用 docker0 路由Docker 会给它们默认分配一个可用的 IP 地址Docker 中所有的网络接口都是虚拟的因为虚拟网卡转发效率高传输文件快。移除容器之后分配给它的虚拟网卡自动消失对应的网桥就没了。
关于自定义网络
Docker 中的自定义网络修复了 docker0 不能使用名字 ping 连接的问题给不同的集群使用不同的自定义网络可以保证集群的安全和健康。
关于跨网络连通
假设容器之间要跨网络通信其中一个容器需要拥有多个 IP 地址。 三、清空 Docker 环境
在之前的 Docker 学习中我们下载 / 提交 / 构建了很多镜像运行了各种不同的容器真是不错的收获现在我们将进入 Docker 网络的学习为了便于学习和理解 Docker 网络的内部原理我们先清空一下 Docker 环境把里面的镜像和容器通通删除。
当然啦如果有特别想要保留的镜像就把它们发布到阿里云镜像仓库吧。发布镜像请参考这篇文章
不清空也没有关系就是会看着有亿点点乱罢了。
删除镜像 / 容器命令
# 删除所有 docker 容器
docker rm -f $(docker ps -aq)# 删除所有 docker 镜像
docker rmi -f $(docker images -aq)# 查看是否删除成功
docker images # 查看所有 docker 镜像
docker ps -a # 查看所有 docker 容器四、介绍 Docker0
1. 理解网络 Docker0
删除完成后我们来查看 Linux 宿主机网络
[rootlocalhost ~]# ip addr
1: lo: 本机回环地址
2: eth0: 阿里云内网地址
3: docker0: docker0 地址
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
# 172.17.0.1 相当于一个路由器 网关通过查询发现Linux 宿主机中一共有 3 个网络除却本机回环地址 127.0.0.1以及本机内网地址剩下的 docker0 便与 Docker 网络相关了。
当我们在 Linux 宿主机中安装了 Docker
宿主机中就会配置 docker0 网卡docker0 使用的是 Linux 桥接模式使用的技术是 Veth-pair 技术。每启动一个 Docker 容器Docker 就会给该容器分配一个 ip一对虚拟网卡。 2. 提前解决报错
由于远程仓库中的 tomcat 镜像是精简版的镜像内部缺少 iproute2 和 iputils-ping 依赖直接使用此镜像来运行是无法使用 ip 命令的会报出如下错误
OCI runtime exec failed: exec failed: unable to start container process: exec: ip: executable file not found in $PATH: unknown
OCI runtime exec failed: exec failed: unable to start container process: exec: ping: executable file not found in $PATH: unknown不要慌解决办法也很简单就是自己安装一下 iproute2 和 iputils-ping 依赖。
因为后面我们要运行好多容器手动给每个容器都去安装一遍的话就显得累赘所以我们把这个容器 commit 为本地镜像。
安装 iproute2 和 iputils-ping 方法
# 1. 用基础镜像 tomcat 运行一个容器 tomcat01
docker run -d -P --name tomcat01 tomcat# 2. 进入容器
docker exec -it tomcat01 /bin/bash# 3. 更新 apt安装 iproute2安装 iputils-ping
apt-get update
apt install -y iproute2
apt install -y iputils-ping# 4. 安装完以后退出 exit
# 5. 提交 容器 tomcat01 为本地镜像
docker commit -ayuanyuan -madd apt ip and ping tomcat01 yuanyuan/tomcat3. 一对虚拟网卡
那么Docker 如何处理网络访问或者说两个 Docker 容器之间如何通信
我们在 Docker0 网络下运行两个 tomcat 容器来进行测试。
查看容器 tomcat01 内部的网络地址
追加命令ip addr
docker exec -it 容器名 ip addr# tomcat01 的 ip 172.17.0.2
[rootlocalhost ~]# docker exec -it tomcat01 ip addr
144: eth0if145: inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0每启动一个 Docker 容器Docker 就会给该容器分配一个 ip一对虚拟网卡。
我们发现容器 tomcat01 启动时得到了 Docker 分配的 ip 地址和虚拟网卡。
ip 地址172.17.0.2一对虚拟网卡144: eth0if145 思考Linux 宿主机可以同 容器 tomcat01 通信吗
通过宿主机 ping 容器 ip 的方式我们来测试一下发现可以 ping 通因为它们在同一网段。
[rootlocalhost ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq1 ttl64 time0.124 ms此时我们再来查看 Linux 宿主机网络
# Linux 多了一对虚拟网卡
[rootlocalhost ~]# ip addr
3: docker0: docker0 inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
145: veth57938f5if144: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc发现 Linux 多了一对虚拟网卡这对虚拟网卡和 tomcat01 有很大的联系。 再创启动一个 tomcat02 容器试试
# 镜像 yuanyuan/tomcat 是我们刚刚提交的那一个
docker run -d -P --name tomcat02 yuanyuan/tomcat然后查看一下 Linux 的网络Linux 又多了一对虚拟网卡。
# Linux 又多了一对虚拟网卡
[rootlocalhost ~]# ip addr
3: docker0: docker0 inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
145: veth57938f5if144: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc
149: veth31fb2d8if148: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc查看下 tomcat02 容器的网络配置
# tomcat02 ip 172.17.0.3; 虚拟网卡 148: eth0if149
[rootlocalhost ~]# docker exec -it tomcat02 ip addr
148: eth0if149: inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0容器的虚拟网卡和宿主机的虚拟网卡是相对应的
随着容器带来的虚拟网卡都是一对一对的这便是 Veth-pair 技术。
Veth-pair 是一对虚拟设备接口它们都是成对出现的一端连接协议一端彼此相连。正因为有这个特性Veth-pair 能充当桥梁来连接各种虚拟网络设备。 4. 使用 Docker0
由于容器 tomcat01 和 tomcat02 都是通过 Docker0 方式桥接的所以它们之间能够通信但是只能通过 ip 地址不能用名字。
我们测试一下上述容器 tomcat01 和 tomcat02 之间能否 ping 通。
用 tomcat02 ping tomcat01反之亦然
[rootlocalhost ~]# docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq1 ttl64 time0.076 ms不难发现容器和容器之间是可以互相 ping 通的。
绘制一个网络模型图来加深理解tomcat01 想要和 tomcat02 通信得借助 docker0 这个路由器。 现在我们把 tomcat01 容器删除
docker rm -f tomcat01再次查看 Linux 的网络配置发现 tomcat01 容器对应的网桥被一同移除了。
# 删掉容器少了一对虚拟网卡对应的网桥就没了
[rootlocalhost ~]# ip addr
3: docker0: inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
149: veth31fb2d8if148: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc关于局域网的知识补充
每个 IP 地址由二进制的四段组成00000000.00000000.00000000.00000000每一段的范围是 0~255。
比如有这样一个子网掩码 255.255.0.0/16这里转换成十进制表示
16 表示 IP 的前 16 位用来固定网段 255.255后 16 位用来给局域网内设备分配 IP255.255.0.1 一般是路由器网关。
那么 IP 为 255.255.xxx.xxx 这样的设备都在这个局域网中可以互相 ping 通。 关于 Docker0 的结论
Docker 容器 tomcat01 和 tomcat02二者共用一个路由器即 docker0所有容器在不指定网络的情况下都使用 docker0 路由Docker 会给它们默认分配一个可用的 IP 地址Docker 中所有的网络接口都是虚拟的因为虚拟网卡转发效率高传输文件快。移除容器之后分配给它的虚拟网卡自动消失对应的网桥就没了。
如图所示Docker 使用 Veth-pair 技术实现容器间的通信。 5. 查看网络模式
我们来查看一下 Docker 中的几种网络模式
bridge桥接模式默认的 docker0 用的就是这种host和宿主机共享网络none不配置网络container容器网络连通这种用得少局限性很大
[rootlocalhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
949536a4c28c bridge bridge local
03fb5b594ce1 host host local
1e8dd7dab9b3 none null local然后具体查看一下桥接模式 bridge
Subnet子网掩码Gateway网关Containers给容器分配的默认 IP 信息
[rootlocalhost ~]# docker network inspect 949536a4c28c
{Subnet: 172.17.0.0/16,Gateway: 172.17.0.1
}# 如果容器没有指定 IPdocker0 会随机分配
Containers: {Name: tomcat01, IPv4Address: 172.17.0.2/16,
}五、容器互联
1. Link 方式 思考一个场景假如我们编写了一个微服务需要连接数据库但数据库每次启动 ip 都会发生变化为了使得微服务不受数据库 ip 变化的影响我们希望通过名字来进行数据库访问实现微服务的高可用。 在默认的 docker0 中添加 --link 参数可以达到这个要求。
重新运行一个 tomcat01 容器吧
docker run -d -P --name tomcat01 yuanyuan/tomcat默认 docker0 情况下容器之间只能通过 ip 来 ping名字是 ping 不通的。
试一下吧用 tomcat02 ping tomcat01直接 ping 容器名字。
[rootlocalhost ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known名字 ping 不通怎么解决呢添加 --link 参数。
我们再运行一个新的容器 tomcat03 测试下把 tomcat03 link 到 tomcat02
docker run -d -P --name tomcat03 --link tomcat02 yuanyuan/tomcat测试 tomcat02 和 tomcat03 之间用名字 ping 一下tomcat03 可以 ping tomcat02但 tomcat02 不可以 ping tomcat03。
# tomcat03 ping tomcat02 可以
[rootlocalhost ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq1 ttl64 time0.202 ms# tomcat02 ping tomcat03 不可以
[rootlocalhost ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known为什么呢inspect 探究一下吧。可以在 tomcat03 容器中找到 Link 配置而 tomcat02 容器中没有配置。
[rootlocalhost ~]# docker inspect tomcat03
Links: [/tomcat02:/tomcat03/tomcat02]也可以通过查看 hosts 配置来发现原理。tomcat03 在本地配置了 tomcat02 的配置它把 tomcat02 直接写入了 hosts 文件ping tomcat02 / b71a0a6566a3 就相当于 ping 对应的 ip 172.17.0.3。
tomcat02 的 hosts 文件里就没有写 tomcat03大家可以查看验证一下。
# --link 就是在 tomcat03 的 hosts 里绑定了 172.17.0.3 tomcat02 b71a0a6566a3[rootlocalhost ~]# docker exec -it tomcat03 cat /etc/hosts
172.17.0.3 tomcat02 b71a0a6566a3这就是为什么 tomcat03 可以 ping tomcat02但 tomcat02 不可以 ping tomcat03 的原因啦。 2. 自定义网络
创建自定义网络
之前是使用的是默认网络 docker0
# 我们直接启动命令 --net bridge就是 docker0
# 以下两条命令是等同的--net bridge 默认情况下可以省略。
docker run -d -P --name tomcat01 yuanyuan/tomcat
docker run -d -P --name tomcat01 --net bridge yuanyuan/tomcat先清空一下容器
docker rm -f $(docker ps -aq)接下来我们自定义一个桥接网络 mynet配置两个容器到 mynet 网络中。
创建一个自定义网络
--driver设置网络模式--subnet设置子网掩码--gateway设置网关mynet自定义网络的名字。
# 创建一个自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet# 查看网络模式
docker network ls# 查看自定义网络 mynet 的详细信息
docker network inspect mynet启动两个容器 tomcat-net-01 和 tomcat-net-02把 tomcat 发布到自定义网络中。
# 运行容器
docker run -d -P --name tomcat-net-01 --net mynet yuanyuan/tomcat
docker run -d -P --name tomcat-net-02 --net mynet yuanyuan/tomcat# 查看 mynet 给容器们分配的 ip
docker network inspect mynet测试 ping 连接
接下来我们测试一下 tomcat-net-01 (192.168.0.2) 和 tomcat-net-02 (192.168.0.3) 之间的 ping 连接。
tomcat-net-01 ping 192.168.0.3成功tomcat-net-01 ping tomcat-net-02成功tomcat-net-02 ping tomcat-net-01成功
# 现在不使用 --link 也可以 ping 名字了# tomcat-net-01 ping 192.168.0.3
[rootlocalhost ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq1 ttl64 time0.092 ms# tomcat-net-01 ping tomcat-net-02
[rootlocalhost ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq1 ttl64 time0.135 ms# tomcat-net-02 ping tomcat-net-01
[rootlocalhost ~]# docker exec -it tomcat-net-02 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq1 ttl64 time0.046 ms关于自定义网络
Docker 中的自定义网络修复了 docker0 不能使用名字 ping 连接的问题给不同的集群使用不同的自定义网络可以保证集群的安全和健康。 六、跨网络连通
1. 连通方式
当前在 Linux 宿主机中有两个 Docker 网络分别是 docker0 和 mynet两个都是桥接模式网段不同。
如图所示在 docker0 局域网中运行了 container01 和 container02 两个容器在 mynet 局域网中运行了 container03 和 container04 两个容器。
在不经过多余配置的情况下container01 和 container03 是无法通信的就是 ping 不通的。
那如果container01 就非常想和 container03 通信有啥办法嘛
首先docker0 和 mynet 这两个网段肯定是不能打通的否则就违背了我们给不同的集群使用不同的自定义网络的初衷。
那么container01 就只能取得 mynet 的联系了。
container01 先联络上 mynet再通过 mynet 联络上 container03。 2. 操作实现
在 docker0 中运行两个容器 tomcat01tomcat02之前的被删了。
不死心tomcat01 先去 ping 一下 mynet 中的 tomcat-net-01
docker run -d -P --name tomcat01 yuanyuan/tomcat
docker run -d -P --name tomcat02 yuanyuan/tomcat# tomcat01 ping tomcat-net-01
[rootlocalhost ~]# docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known显然tomcat01 ping tomcat-net-01失败咯。 那么tomcat01 要怎么联络上 mynet 呢我们来研究一下 docker 中 network 的使用方法。
docker network --help# 发现了 connect 方法连接一个容器到一个网络
[rootlocalhost ~]# docker network --help
Usage: docker network COMMAND
Commands:connect Connect a container to a network测试连接 tomcat01 容器和 mynet 网络
# 测试打通 tomcat01--mynet
docker network connect mynet tomcat01现在再尝试 tomcat01 ping tomcat-net-01会发现成功了
而且 tomcat01 不仅可以通信 tomcat-net-01也可以通信 tomcat-net-02tomcat01 可以和 mynet 中任何一个容器通信。
但是和 tomcat01 一起的 tomcat02 就依然不行。
# tomcat01 ping tomcat-net-01 可以
[rootlocalhost ~]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq1 ttl64 time0.115 ms# tomcat01 ping tomcat-net-02 可以
[rootlocalhost ~]# docker exec -it tomcat01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq1 ttl64 time0.081 ms# tomcat02 ping tomcat-net-01 不行哦
[rootlocalhost ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known3. 一个容器两个 IP
这是怎么实现的呀就是给 tomcat01 加了一个 IP这个容器现在有两个 IP 地址了一个在原来的 docker0 下另一个在 mynet 下。
这就好比阿里云服务器它有一个公网 IP 和一个私网 IP。
可以在 mynet 配置中查看 tomcat01 的配置信息
docker network inspect mynetName: tomcat01,
IPv4Address: 192.168.0.4/16七、总结
本文介绍了 Docker 网络原理介绍了 docker0Veth-pair 技术以及 Docker 给容器分配虚拟网卡的方式。同时讲述了两种容器互联的方式分别是 Link 和 自定义网络。还有容器之间跨网络连通的方式。
一些参考资料
狂神说系列 Docker 教程https://www.bilibili.com/video/BV1og4y1q7M4/ Docker 官方文档https://docs.docker.com/engine/install/centos/ Docker 远程仓库https://hub.docker.com/ FinalShell 下载http://www.hostbuf.com/t/988.html