速通Docker === 网络

目录

Docker网络详解

容器之间直接通信的弊端

(一)启动容器

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

(三)请求流程

[(四) 弊端分析](#(四) 弊端分析)

一、Docker网络基础

(一)容器IP分配

(二)默认网络docker0

二、自定义网络机制

(一)创建自定义网络

(二)查看Docker网络

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

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

三、总结


Docker网络详解

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

容器之间直接通信的弊端

(一)启动容器

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

复制代码
 docker run -d -p 88:80 --name app1 nginx
 docker 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:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 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技术,提高开发效率和系统稳定性。

相关推荐
小张是铁粉5 分钟前
docker学习二天之镜像操作与容器操作
学习·docker·容器
烟雨书信18 分钟前
Docker文件操作、数据卷、挂载
运维·docker·容器
IT成长日记21 分钟前
【Docker基础】Docker数据卷管理:docker volume prune及其参数详解
运维·docker·容器·volume·prune
这儿有一堆花27 分钟前
Docker编译环境搭建与开发实战指南
运维·docker·容器
LuckyLay28 分钟前
Compose 高级用法详解——AI教你学Docker
运维·docker·容器
Uluoyu36 分钟前
redisSearch docker安装
运维·redis·docker·容器
IT成长日记5 小时前
【Docker基础】Docker数据持久化与卷(Volume)介绍
运维·docker·容器·数据持久化·volume·
热爱生活的猴子5 小时前
阿里云服务器正确配置 Docker 国内镜像的方法
服务器·阿里云·docker
FrankYoou9 小时前
Jenkins 与 GitLab CI/CD 的核心对比
java·docker
隆里卡那唔9 小时前
在dify中通过http请求neo4j时为什么需要将localhost变为host.docker.internal
http·docker·neo4j