当前位置: 首页 > news >正文

速通Docker === 网络

目录

Docker网络详解

容器之间直接通信的弊端

(一)启动容器

(二)进入容器并发起请求 

(三)请求流程

(四) 弊端分析

一、Docker网络基础

(一)容器IP分配

(二)默认网络docker0

二、自定义网络机制

(一)创建自定义网络

(二)查看Docker网络

(三)容器启动时指定自定义网络

(四)使用容器名称作为域名进行访问

三、总结



Docker网络详解

在当今的软件开发与部署领域,Docker凭借其强大的容器化技术,已成为众多开发者的得力助手。而Docker网络作为连接容器与外部世界的关键桥梁,更是至关重要。本文将深入讲解Docker网络的相关知识,帮助你更好地理解和运用这一技术。


容器之间直接通信的弊端

(一)启动容器

首先,通过以下两条命令启动了两个Nginx容器:

 docker run -d -p 88:80 --name app1 nginxdocker run -d -p 99:80 --name app2 nginx

(二)进入容器并发起请求 

接着,执行以下命令进入app1容器,并发起对http://xxx:99/的请求:(容器二)

docker exec -it app1 bash
  • docker exec 是在运行的容器中执行命令的指令。

  • -it 参数使我们能够与容器的终端进行交互。

  • bash 是要执行的命令,即启动一个bash shell。

进入容器后,执行以下命令发起请求:

curl http://xxx:99/
  • curl 是一个常用的命令行工具,用于发起网络请求。

  • http://xxx:99/ 是请求的URL,指向宿主机的99端口,即app2容器中的Nginx服务。

(三)请求流程

  1. 本地网络解析:当在app1容器中执行curl命令时,首先会通过容器内部的网络配置(如DNS设置等)对目标URL进行解析,确定目标IP地址和端口。

  2. 容器间通信:由于app1和app2都运行在同一台宿主机上,且通过Docker网络连接,请求会从app1容器的网络栈发出,经过Docker的网络桥接设备,到达app2容器。

  3. Nginx处理请求:app2容器中的Nginx服务接收到请求后,会根据其配置文件(通常位于/etc/nginx/nginx.conf)进行处理。对于默认的Nginx配置,它会返回一个欢迎页面,表明Nginx服务已成功安装并运行。

  4. 响应返回:处理完请求后,Nginx将响应数据发送回app1容器,app1容器的curl命令会接收到响应内容并显示在终端上。

(四) 弊端分析

  • 跨容器通信:虽然app1和app2容器运行在同一台宿主机上,但它们之间的通信需要经过Docker的网络桥接设备。这相比直接在宿主机上进行进程间通信,会增加一定的网络性能开销。数据需要在容器的虚拟网络接口之间传输,经过网络协议栈的处理,这可能会导致延迟增加和吞吐量降低。

  • 端口映射:通过宿主机的端口映射访问容器服务时,Docker需要在宿主机的网络栈中进行端口转发。这个过程会增加网络数据包的处理时间,尤其是在高并发请求场景下,可能会成为性能瓶颈。

  • IP地址变化:Docker容器的IP地址可能会发生变化。如果在容器之间通过IP地址进行通信,每次IP地址变化时,都需要更新相关的配置文件或代码,这会增加维护成本。例如,如果app2容器的IP地址发生变化,app1容器中的请求URL也需要相应地进行修改,否则会导致请求失败。

一、Docker网络基础

(一)容器IP分配

Docker为每个容器分配了唯一的IP地址,使得容器之间可以通过IP地址加端口的方式进行互相访问。例如,当我们在同一台宿主机上运行多个容器时,每个容器都会获得一个独立的IP,如172.17.0.2、172.17.0.3等。这种IP分配机制使得容器之间的通信变得更加直观和便捷。然而,需要注意的是,由于容器的动态性以及Docker网络的配置变化等原因,这些IP地址可能会发生变化,这就给容器之间的稳定通信带来了一定的挑战。

(二)默认网络docker0

当每个应用启动时,Docker会自动将其加入到一个名为docker0的默认网络中。docker0是一个虚拟的以太网桥,它在宿主机上创建了一个网络接口,并为连接到它的容器提供网络连接服务。我们可以通过执行ip addr命令来查看docker0的相关信息,如下所示:

6: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:63:90:8e:52 brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:63ff:fe90:8e52/64 scope link

IPv4 vs IPv6

IPv4

  • 格式:由4组数字组成,每组数字范围是0-255,用点号隔开,比如“192.168.1.1”。就像一个4位的“数字密码锁”,每一位有256种可能的数字。

  • 数量:总共大约有43亿个地址。可以想象成一个有43亿个房间的大楼,每个房间有一个独特的房间号(即IP地址),早期互联网设备较少时够用,但随着设备越来越多,房间就不够住了。

IPv6

  • 格式:由8组数字或字母组成,每组有4个字符,用冒号隔开,比如“2001:0db8:85a3:0000:0000:8a2e:0370:7334”。它就像一个8位的“密码锁”,每一位可以是数字0-9或字母a-f,组合方式更多。

  • 数量:地址数量极其庞大,理论上可以提供约3.4×10^38个地址。就好像有无数个宇宙,每个宇宙都有无数个星球,每个星球上都有无数个房间,每个房间都有一个独特的IPv6地址,几乎不用担心地址会用完,能够满足未来大量设备接入互联网的需求。

子网掩码 vs ip

在IP地址中,每个数字(0-255)实际上是8位二进制数。IPv4地址由4个这样的数字组成,总共是32位。例如,IP地址“172.17.0.1”可以转换为二进制表示为:

10101100.00010001.00000000.00000001

每个数字(0-255)对应8位二进制数。所以,“172.17”在二进制中表示为:

10101100.00010001

这16位二进制数就是网络部分,表示这个IP地址属于“172.17”这个网络。剩下的16位二进制数(“00000000.00000001”)是主机部分,用于标识网络中的不同设备。

因此,“172.17.0.1/16”中的“/16”表示前16位是网络部分,后16位是主机部分。具体来说:

  • 网络部分:10101100.00010001(即“172.17”)

  • 主机部分:00000000.00000001(即“0.1”)

这样,整个网络的IP地址范围是“172.17.0.0”到“172.17.255.255”,因为主机部分可以是“0.0”到“255.255”。

子网掩码

  • 作用:用于区分IP地址中的网络部分和主机部分。在IPv4地址中,子网掩码长度为16位,意味着前16位是网络地址,后16位是主机地址。

  • 具体解释

    • 网络地址:前16位“172.17”是网络地址,表示该IP地址属于“172.17”这个网络。在这个网络中,所有IP地址的前16位都是相同的,即“172.17”。

    • 主机地址:后16位“0.1”是主机地址,用于标识网络中的不同设备。在这个网络中,主机地址的范围是“0.0”到“255.255”,即“172.17.0.0”到“172.17.255.255”。

  • 例子

    • IP地址:172.17.0.1

    • 子网掩码:255.255.0.0(等同于16位)

    • 网络地址:172.17.0.0

    • 主机地址:0.1

总结

  • 子网掩码长度16位表示IP地址的前16位是网络部分,后16位是主机部分。在这个例子中,“172.17”是网络地址,“0.1”是主机地址,整个网络的IP地址范围是“172.17.0.0”到“172.17.255.255”。

从上述信息中,我们可以看到docker0的IP地址为172.17.0.1,子网掩码为16位,这表明它管理着172.17.0.0/16这个网段的IP地址分配。同时,我们还可以通过执行docker [container] inspect <image name>命令来查看容器的详细信息,包括其所属网络的配置。在Networks配置项中,我们可以找到网关(Gateway)和IP地址(IPAddress)等关键信息,如下所示:

docker [container] inspect <image name>

"Networks": {"bridge": {  // 表示该容器使用的网络模式为桥接模式"IPAMConfig": null,  // IP地址管理配置,此处为空表示使用默认配置"Links": null,  // 容器之间的连接配置,此处为空表示没有特殊连接"Aliases": null,  // 容器在网络中的别名,此处为空表示没有设置别名"MacAddress": "02:42:ac:11:00:02",  // 容器的MAC地址"DriverOpts": null,  // 网络驱动选项,此处为空表示使用默认驱动选项"NetworkID": "af5288f6a00acbba4577b5e2d80414344ee55254b663fafa1bc60713252ac088",  // 网络的唯一标识符"EndpointID": "3c2530d77688b6be17e4ec6499716d0d946f4dcec6cfbf5738b665823880f047",  // 容器在网络中的端点标识符"Gateway": "172.17.0.1",  // 网关地址,即容器访问外部网络的中转站地址"IPAddress": "172.17.0.2",  // 容器的IP地址"IPPrefixLen": 16,  // IP地址的子网掩码长度,此处表示子网掩码为255.255.0.0"IPv6Gateway": "",  // IPv6网关地址,此处为空表示未配置IPv6网关"GlobalIPv6Address": "",  // 全局IPv6地址,此处为空表示未配置全局IPv6地址"GlobalIPv6PrefixLen": 0,  // 全局IPv6地址的前缀长度,此处为0表示未配置"DNSNames": null  // DNS名称,此处为空表示没有设置DNS名称}
}

 扫盲专区 

网关与IP简介

  • IP地址:就像我们每个人的身份证号码一样,IP地址是网络中设备的唯一标识。在这个例子中,“172.17.0.2”就是该容器在所在网络中的“身份证号码”,通过这个地址,网络中的其他设备就可以找到并和它进行通信。

  • 网关:可以理解为一个“中转站”。当容器想要访问外部网络(比如互联网)时,它会先把数据发送到“172.17.0.1”这个网关地址,然后网关会负责把数据转发到外部网络。简单来说,网关就像是一个桥梁,帮助容器从内部网络走向外部世界。

二、自定义网络机制

为了克服默认网络docker0在稳定性和灵活性方面的不足,Docker提供了自定义网络机制。通过创建自定义网络,我们可以更好地管理和控制容器之间的通信,实现更加稳定和高效的网络访问。

(一)创建自定义网络

创建自定义网络非常简单,只需执行以下命令:

docker network create <network_name>

例如,我们可以创建一个名为mynet的自定义网络:

docker network create mynet

执行该命令后,Docker会自动创建一个新的网络,并为其分配一个唯一的网络ID。

(二)查看Docker网络

要查看所有已创建的Docker网络,可以使用以下命令:

docker network ls

该命令会列出所有网络的名称、ID、驱动程序等信息,方便我们进行管理和查询。

(三)容器启动时指定自定义网络

在启动容器时,我们可以通过--network参数指定容器加入到某个自定义网络中。例如:

docker run -d -p 88:80 --name app1 --network mynet nginx

该命令会启动一个名为app1的Nginx容器,并将其加入到mynet自定义网络中。通过这种方式,我们可以将多个容器组织到同一个网络中,实现它们之间的稳定通信。

(四)使用容器名称作为域名进行访问

当容器加入到自定义网络后,我们可以使用容器的名称作为域名进行访问。例如,假设我们有两个容器app1和app2,它们都加入了mynet自定义网络。我们可以在app1容器中执行以下命令来访问app2容器:

docker exec -it app1 bash
root@411c92f75eb1:/# curl http://app2:80

通过这种方式,我们可以实现容器之间的稳定通信,而无需关心容器IP地址的变化。这大大提高了容器网络的可管理性和可维护性。

三、总结

Docker网络是容器化技术中的重要组成部分,它为容器之间的通信提供了强大的支持。通过了解Docker网络的基础知识,如容器IP分配和默认网络docker0,我们可以更好地理解容器的网络连接机制。而自定义网络机制则为我们提供了更加灵活和稳定的网络管理方式,通过创建自定义网络、指定容器加入网络以及使用容器名称作为域名进行访问,我们可以实现容器之间的高效通信,满足各种复杂的网络需求。掌握Docker网络的相关知识,将有助于我们在软件开发和部署过程中更加得心应手地运用Docker技术,提高开发效率和系统稳定性。

http://www.lryc.cn/news/523920.html

相关文章:

  • 【MySQL — 数据库基础】深入解析MySQL常用数据类型
  • Linux高级--3.3.1 C++ spdlog 开源异步日志方案
  • 电梯系统的UML文档05
  • 如何使 LLaMA-Factory 支持 google/gemma-2-2b-jpn-it 的微调
  • MySQL中日期和时间戳的转换:字符到DATE和TIMESTAMP的相互转换
  • HarmonyOS NEXT开发进阶(十):UIAbility 组件交互
  • 深入探索Math.NET:开启高效数值计算之旅
  • AI编程工具横向评测--Cloudstudio塑造完全态的jupyter notebook助力数据分析应用开发
  • 【2024 CSDN博客之星】技术洞察类:从DeepSeek-V3的成功,看MoE混合专家网络对深度学习算法领域的影响(MoE代码级实战)
  • Linux——入门基本指令汇总
  • 54,【4】BUUCTF WEB GYCTF2020Ezsqli
  • 【Leetcode 热题 100】45. 跳跃游戏 II
  • C/C++ 时间复杂度(On)
  • 【STM32-学习笔记-10-】BKP备份寄存器+时间戳
  • React 中hooks之 React.memo 和 useMemo用法总结
  • 日志收集Day001
  • 机器人“大脑+小脑”范式:算力魔方赋能智能自主导航
  • python程序跑起来后,然后引用的数据文件发生了更新,python读取的数据会发生变化吗
  • VSCode最新离线插件拓展下载方式
  • 算法题目总结-栈和队列
  • IO进程----进程
  • 【机器学习实战高阶】基于深度学习的图像分割
  • 「免填邀请码」赋能各类APP,提升转化率与用户体验
  • 基于海思soc的智能产品开发(视频的后续开发)
  • 创建 pdf 合同模板
  • 2024 年度学习总结
  • CSS笔记基础篇02——浮动、标准流、定位、CSS精灵、字体图标
  • C++ 面向对象(继承)
  • Top期刊算法!RIME-CNN-BiLSTM-Attention系列四模型多变量时序预测
  • 数据结构 数组