Docker 容器化技术:构建高效、可移植的开发环境和部署流程|Docker 网络

news2025/1/15 23:45:01

为了支持网络协议栈的多个实例,Linux 在网络协议栈中引入了网络命名空间。这些独立的协议栈被隔离到不同的命名空间中,处于不同命名空间中的网络协议栈是完全隔离的,彼此无法通信。通过对网络资源的隔离,就能在一台宿主机上虚拟多个不同的网络环境,Docker 正是利用了网络的命名空间特性,实现不同容器之间的网络隔离。

在 Linux 的网络命名空间中,每个空间都拥有独立的路由表和 iptables 设置,负责包转发、网络地址转换(NAT)和 IP 包过滤等功能。由于网络命名空间代表独立的协议栈,它们相互隔离且无法直接通信。但 Docker 通过虚拟接口 veth 实现了容器之间以及容器与宿主机之间的通信。虚拟以太网(veth)以成对的形式出现,就像管道的两端一样。数据从一个 veth 进入,经过协议栈后,从另一个 veth 出去,打通了互相隔离的协议栈之间的壁垒。通过连接两个网络命名空间或全局命名空间,veth 可以将物理网卡存在的命名空间内进行通信。要在两个网络命名空间之间实现通信,必须有一对虚拟接口对。

2、Linux 网络虚拟化

Docker 利用了 Linux 上的网络命名空间和虚拟网络设备来实现本地网络功能。了解 Linux 网络虚拟化技术有助于理解 Docker 网络的实现过程,其中 Linux 网络虚拟化是 LXC 项目的一部分。LXC 包括文件系统虚拟化、进程空间虚拟化、用户虚拟化和网络虚拟化等。

Docker 使用了LXC的网络虚拟化来模拟多个网络环境。Linux网络虚拟化主要有以下类型:

  • 桥接:创建虚拟桥设备(网桥),将虚拟机连接至桥设备上,再配置桥设备的 IP 地址,即可与外部通信。此时虚拟机使用的是公网地址
  • 隔离:将需要通信的虚拟机的网卡添加到同一个虚拟桥设备上,实现虚拟机之间的通信,与外网仍然隔离
  • 路由:将虚拟机关联至虚拟桥设备上,配置与虚拟机同段的 IP 地址作为虚拟机的网关,最后打开物理主机的核心转达功能,实现虚拟机与外部主机的通信
  • NAT:在路由模型的基础上,配置源地址转换(SNAT)规则,实现虚拟机与外网通信,但自己使用的是内网地址。外网无法主动访问内网的虚拟机,需要额外配置目标地址转换(DNAT)规则

Docker 中的网络接口默认为虚拟接口,其最大优势是转发效率高。Linux 通过在内核中进行数据复制来实现虚拟接口之间的数据转发,即直接将发送接口的数据包复制到接收接口的缓存中,无需通过外部物理网络设备进行交换。对于本地系统和容器内系统而言,虚拟接口和普通以太网卡没有区别,但速度更快。
Docker 容器网络利用了 Linux 虚拟网络技术,通过在本地宿主机和容器内部创建虚拟接口 veth 并连接二者,这样的一对虚拟接口称为 veth pair。

通常情况下,Docker 创建容器时执行以下操作:

  • 创建一对虚拟接口,一个放在本地宿主机,另一个放在新容器的命名空间中
  • 将本地宿主机端的虚拟接口连接到默认的网桥 docker0(实际上是一个 Linux 网桥)或指定的网桥上,并赋予一个以 veth 开头的唯一名称,如 veth18
  • 将容器端的虚拟接口放置到新创建的容器中,并将其名称修改为 eth0。此接口仅在容器的命名空间中可见
  • 从网桥可用地址段中获取一个空闲地址,分配给容器的 eth0 接口(如172.10.0.22/16),并配置默认路由网关为 docker0 网桥的内部接口IP地址(如172.10.1.1/16)

完成上述操作后,Docker 在宿主机和所有容器之间创建了一个虚拟共享网络。容器可以使用其可见的 eth0 虚拟网卡连接其他容器并访问外部网络。在使用 docker [container] run 命令启动容器时,可以通过--net参数指定容器的网络配置。目前有5个可选值,分别是 bridge、container、host、none 和自定义网络。

3、Docker 网络架构

前面介绍了使用 -p 参数实现 Docker 容器与宿主机端口的映射,以及通过--link参数实现容器之间的网络通信。随着 Docker 的不断发展,其网络架构也在逐步演进。

与虚拟机或物理机不同,Docker 容器内部运行的应用程序需要大量不同类型的网络交互,这要求 Docker 具备强大的网络功能。幸运的是,Docker 提供了一套完整的解决方案,用于容器之间、容器与外部网络以及虚拟局域网(VLAN)之间的连接。这对于需要与外部系统(如虚拟机和物理机)进行通信的容器化应用至关重要。

Docker 1.9 版本引入了一套完整的 docker network 子命令和跨主机网络支持。用户可以通过 docker network --help 查看 Docker 网络命令的详细说明。这使得用户可以根据其应用程序的拓扑架构创建虚拟网络,并将容器连接到相应的网络上。事实上,在 Docker 1.7 版本中,网络部分代码就已经被抽离并单独形成了 Docker 的网络库,即 Libnetwork。随后,容器的网络模式被抽象成了统一接口的驱动。

为了标准化网络驱动的开发流程并支持多种网络驱动,Docker 在 Libnetwork 中采用了容器网络模型(CNM)。CNM 定义了构建容器虚拟化网络的模型,并提供了用于开发多种网络驱动的标准接口和组件。Libnetwork 是 Docker 对 CNM 的一种实现,提供了 Docker 核心网络架构的全部功能。不同的驱动可以通过插拔的方式接入 Libnetwork,以提供定制化的网络拓扑。为了实现即插即用的效果,Docker 封装了一系列本地驱动,覆盖了大部分常见的网络需求,包括单机桥接网络、多机覆盖网络,以及支持接入现有 VLAN。Libnetwork 与 Docker 守护进程及各个网络驱动之间的关系如图所示。

Docker 网络架构主要由 CNM、Libnetwork 和驱动三个主要部分组成。Docker 守护进程通过调用 Libnetwork 提供的 API 完成网络的创建和管理等功能;Libnetwork 则使用 CNM 来实现网络功能的提供;而 CNM 主要包括沙盒、接入点和网络三种组件。

Libnetwork 内置了 5 种驱动,为 Libnetwork 提供了不同类型的网络服务。

4、容器网络模型

Libnetwork 中的容器网络模型(CNM)简洁而精致,规定了 Docker 网络的基础组成要素,使得上层容器可以最大程度地摆脱底层实现的烦恼。CNM模型包括以下三种基本组件:

  • 沙盒:代表容器独立的网络栈,包括以太网接口、端口、路由表以及 DNS 配置
  • 接入点:在网络上代表可以连接容器的虚拟接口,会分配 IP 地址。类似于普通网络接入点,接入点主要负责创建连接,在 CNM 模型中,接入点负责将沙盒连接到网络
  • 网络:是一个虚拟子网,可以连接多个接入点,是 IEEE 802.1d 网桥的软件实现

Docker 环境中最小的调度单位是容器,而 CNM 则专注于为容器提供网络功能。下图展示了 CNM 组件如何与容器进行关联,沙盒被置于容器内部,为容器提供网络连接。

接入点类似于常见的网络适配器,一个接入点只能连接到一个网络。如果容器需要连接到多个网络,则需要多个接入点。例如,容器 A 只有一个接入点并连接到网络 A,容器 B 有两个接口分别连接到网络 A 和 B。容器 A 和 B 可以相互通信,因为它们都连接到了同一个网络 A。但是,如果没有三层路由器的支持,容器B的两个接入点之间是无法相互通信的。

通过面向接口的分层解耦设计,CNM 实现了关注点的分离,使得容器管理系统无需关心底层网络的实现细节和不同子网之间的隔离。只要插件能够提供网络和接入点,容器管理系统只需连接或断开容器,剩余的工作就交由插件自行处理,实现了容器和网络功能的解耦,具有极高的灵活性。

CNM 网络的创建过程是,Libnetwork 网络驱动将自身注册到网络控制器,网络控制器使用驱动类型创建网络,然后在创建的网络上创建接口,最后将容器连接到接口上。销毁过程则相反,首先从接入点上卸载容器,然后删除接入点和网络即可。

目前 CNM 支持四种网络驱动类型:

  • null:不提供网络服务,容器启动后无网络连接
  • bridge:Docker 传统的单机网络,基于 Linux 网桥和 iptables 实现
  • overlay:跨宿主机容器网络,利用虚拟扩展局域网(VXLAN)隧道技术实现
  • remote:扩展类型,为其他外部实现的方案保留,由第三方编写网络驱动,例如 Calico、Contiv、Kuryr、Weave 等

Libnetwork 位于 Docker 上方支持 Docker,下方支持网络插件,处于十分关键的中间层。熟悉计算机网络协议模型的读者可以将 Libnetwork 视为传输控制协议/网际协议(TCP/IP)层的核心。每个驱动负责管理其上的所有网络资源。为了满足复杂且多变的环境需求,Libnetwork 支持同时激活多个网络驱动,从而支持庞大的异构网络。

5、单机桥接网络

最简单的 Docker 网络是单机桥接网络,从名称中即可了解以下两点:

  • 单机:该网络仅在单个 Docker 宿主机上运行,只能连接到该宿主机上的容器
  • 桥接:这意味着它是 IEEE 802.1d 桥接的一种实现,即二层交换机

每个 Docker 宿主机都默认拥有一个单机桥接网络。在 Linux 上,网络名为 bridge;在 Windows 上,网络名为 NAT。除非在创建容器时明确指定了 --network 参数,否则新创建的容器都会自动连接到该网络。

在 Linux 宿主机上,Docker 网络由 bridge 驱动创建,底层基于 Linux 内核的 Linux 网桥技术。这意味着 bridge 网络具有高性能和稳定性,并且可以通过标准的 Linux 工具进行管理。

默认情况下,Linux Docker 宿主机上的 bridge 网络映射到内核中的 docker0 Linux 网桥。通过 docker network inspect bridge 命令可以查看该虚拟网络的详细信息。

docker0 网桥类似于交换机,用于转发连接到其上的设备的数据帧。网桥上的 veth 网卡设备相当于交换机上的端口,可连接多个容器或虚拟机,工作在二层,无需配置 IP 信息。

在 Docker 的桥接网络模式中,docker0 的 IP 地址作为连接到其上的容器的默认网关地址存在。

在宿主机上安装 Docker 引擎时,Docker 默认会创建 bridge 网络,并且宿主机上的所有容器默认都会连接到此网络。可通过 docker network create 命令创建新的单机桥接网络,并通过在容器启动时使用 docker run 命令的 --network 参数指定容器要连接的网络。

在同一网络中,不同容器可以通过容器名相互访问,因为所有容器都注册在指定的 Docker DNS 服务上。在单机桥接网络模式下,不同网络中的容器要相互访问,则需要使用端口映射来避免容器名解析限制。通过在容器启动时使用 docker run 命令的 -d 参数指定容器与宿主机的端口映射,将容器端口映射到 Docker 宿主机端口上,从而实现访问。

6、多机覆盖网络

覆盖网络适用于跨多个宿主机的环境,它创建了一个扁平、安全的二层网络,用于连接这些宿主机。容器可以连接到覆盖网络并直接相互通信,实现链路层的数据传输。覆盖网络是实现容器间通信的理想方式,具有良好的网络伸缩性。

Docker 提供了本地驱动来支持覆盖网络,该驱动是基于 Libnetwork 和 overlay 驱动构建的,使得创建覆盖网络非常简单,只需在 `docker network create` 命令中添加 `--d overlay` 参数。

overlay 驱动默认使用 VXLAN 协议,在可相互访问的多个宿主机之间建立隧道,从而实现容器之间的互相访问。Docker 使用 VXLAN 隧道技术创建虚拟的二层覆盖网络。VXLAN 是一种封装技术,能够使现有的路由器和网络架构看起来像普通的 IP/UDP 包一样,并且可以无缝处理。为了创建二层覆盖网络,VXLAN 基于现有的三层 IP 网络创建了隧道。

在 VXLAN 的设计中,每个节点之间建立了 VXLAN 隧道,这些节点称为 VXLAN 隧道终端(VTEP)。VTEP 完成了封装和解压缩的操作,以及一些必要的功能实现。在两个节点之间建立 VXLAN 隧道后,为了实现跨节点的容器间互联,我们需要在每个宿主机上创建一个沙盒(网络命名空间)。沙盒类似于容器,但其中运行的是当前宿主机上独立的网络栈。在沙盒内部,创建一个名为 Br0 的虚拟交换机(也称为虚拟网桥)。同时,在沙盒内部创建一个 VTEP,其中一端连接到名为 Br0 的虚拟交换机,另一端连接到宿主机的网络栈(VTEP)。

在宿主机网络栈中,VTEP 从基础网络中获取 IP 地址,并通过 UDP 套接字绑定到 4789 端口(IANA 规定的 UDP 端口)。不同宿主机上的两个 VTEP 通过 VXLAN 隧道创建了一个覆盖网络。

每个容器都有自己的虚拟以太网适配器(veth),并连接到本地虚拟交换机 Br0。目前的拓扑结构如图所示。

虽然宿主机网络相互独立,但位于不同宿主机上的容器可以通过 VXLAN 覆盖网络进行通信。例如,容器 C1(位于节点1)希望 ping 通容器 C2(位于节点2)。C1 发起 ping 请求,目标 IP 为 C2 的地址 10.1.0.8。请求流量通过连接到虚拟交换机 Br0 的 veth 发送出去。Br0 不知道将数据包发送到哪里,因此会将其发送到所有端口。连接到 Br0 的 VTEP 接口知道如何转发这个数据帧,并将自己的 MAC 地址返回给 Br0。这是一个代理 ARP 响应,使得 Br0 学会了如何转发该包。之后,Br0 更新了自己的 ARP 映射表,将 10.1.0.8 映射到本地 VTEP 的 MAC 地址。现在,Br0 已经学会如何转发到 C2 的流量,之后所有发送到 C2 的包都将直接转发到 VTEP 接口。

当包到达节点2后,内核发现目标端口为 UDP Socket 端口 4789,并且知道存在 VTEP 接

口绑定到该 Socket。因此,内核将包发送给 VTEP,VTEP 读取 VNID,解压缩包信息,并根据 VNID 发送到本地连接到 VLAN 的虚拟交换机 Br0。在 Br0 上,包被发送给容器 C2。

7、混合互联网络

在先前的介绍中,讨论了单节点和跨节点下多个 Docker 容器之间的互联互通。然而,在企业的实际 IT 架构中,由于历史原因,大量传统架构的应用需要进行集成。因此,将容器化应用连接到外部系统和物理网络是至关重要的能力。一个常见的场景是部分容器化的应用需要与运行在物理网络和 VLAN 上的未容器化应用进行通信。这就引入了虚拟网络和物理网络之间混合互联的网络架构。

Docker 内置的 macvlan 驱动就是为这种场景而设计的。通过为容器提供 MAC 地址和 IP 地址,macvlan 允许容器在物理网络上成为“一等公民”。

macvlan 本身是一个 Linux 内核模块,其功能是允许在同一个物理网卡上配置多个 MAC 地址,即多个接口,每个接口可以配置自己的 IP 地址。macvlan 本质上是一种网卡虚拟化技术,其优点在于性能优异,因为无需端口映射或额外桥接,可以直接通过主机接口(或子接口)访问容器接口。但缺点是需要将主机网络接口卡(Network Interface Card,NIC)设置为混杂模式(promiscuous mode),而这在大部分公有云平台上是不允许的。因此,macvlan 对于公司内部的数据中心网络来说非常实用(假设公司网络组能接受 NIC 设置为混杂模式),但在公有云上则不可行。

创建 macvlan 网络非常简单,只需在 Docker 创建网络命令 docker network create 中添加 -d macvlan 参数即可。创建的 macvlan 网络可以是 bridge 模式或 802.1q trunk bridge 模式:

  • 在 bridge 模式中,macvlan 流量通过主机上的物理设备
  • 在 802.1q trunk bridge 模式中,流量通过 Docker 在运行中创建的 802.1q 子接口,用户可以更细粒度地控制路由和过滤

8、网络访问控制

Docker 容器的网络访问控制主要通过 Linux 系统上的 iptables 防火墙软件来进行管理和实现。iptables 是 Linux 系统中流行的防火墙软件,在大多数发行版中都自带。

安装完 Docker 后,宿主机系统会默认添加一些 iptables 规则,用于管理 Docker 容器之间以及容器与外部世界的通信。iptables 的工作原理是基于规则,这些规则实际上是由网络管理员预定义的条件。一般情况下,规则定义了如果数据包头符合某种条件,就对这个数据包采取相应的处理方式。这些规则存储在内核空间的信息包过滤表中,其中包括了源地址、目的地址、传输协议(如TCP、UDP、ICMP)以及服务类型(如HTTP、FTP、SMTP)等信息。当数据包与规则匹配时,iptables 会根据规则所定义的方法来处理这些数据包,比如允许通过(accept)、拒绝(reject)或丢弃(drop)等。

配置防火墙的主要任务就是添加、修改和删除这些规则。您可以使用 iptables-save命令来查看宿主机中Docker引擎为我们设置的iptables规则信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1519335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ACW 服务端】页面操作Java增删改查代码生成

版本: 1.2.2-JDK17-SNAPSHOT 项目地址:wu-smart-acw 演示地址:演示地址 admin/admin Java增删改查代码生成 找到对应菜单 选择你需要的数据实例 选择数据库 选择数据库表 选择客户端(如果是本地ACW服务代码启动默认注册上的客户端ID是…

错误:npm ERR! code CERT_HAS_EXPIRED 解决

问题: 在打开项目用npm install安装依赖时报错:npm ERR! code CERT_HAS_EXPIRED如下图: 原因: 说明正在尝试访问的npm registry 淘宝npm镜像源 的SSL证书已经过期,导致无法建立安全连接。 解决: 配置不…

深度学习基础知识之Atrous卷积(空洞卷积)

太久不看代码确实生疏了,盯着一堆不同的dilation,不知道有什么作用,论文中说是Atrous卷积,原来就是空洞卷积的意思。 Dilated/Atrous Convolution 空洞卷积(膨胀卷积/扩张卷积) 空洞卷积是一种不增加参数量…

2024 Meetup地区组织者招募ing!| 共赴IvorySQL城市行

IvorySQL每一次线下活动,都离不开背后默默付出及用心策划的地区组织者。是他们,让我们的相聚变得更加有意义,让我们的交流更加深入。每次看到大家在活动现场热情洋溢的面孔,听到大家对IvorySQL的喜欢和期待,我们都感到…

CSS:过渡动画 (Transition)与关键帧动画(Keyfram)

一、过渡动画 (Transition) 1.简单介绍 Transition能为样式的变化提供过渡效果,例如在下面的代码中: .main {width: 300px;height: 100px;background-color: #d26f6f;}.main:hover {width: 300px;height: 200px;background-color: #5e3e3e;transition:…

vscode 将已修改代码提交推送git时一直转圈也没有反馈

新安装的vscode 将已修改代码提交推送git时一直转圈也没有反馈 第一步 打开设置 第二步 搜索use Editor点击下面得git 第三步 将use Editor As commit input取消勾选 再次进行提交即可

【消息队列开发】 实现内存加载

文章目录 🍃前言🌳实现思路🚩读取消息长度🚩读取相应长度的消息🚩进行反序列化🚩判定是否有效🚩加入有效消息🚩收尾工作🚩代码实现 ⭕总结 🍃前言 本次开发目…

Ansible非标记语言YAML与任务剧本Playbook

前言 上篇介绍了 Ansible 单模块(AD-Hoc)的相关内容Ansible自动化运维Inventory与Ad-Hoc-CSDN博客,Ad-Hoc 命令是一次性的、即时执行的命令,用于在远程主机上执行特定任务,这些命令通常用于快速执行简单的任务。当需要…

二分查找注意事项

目录 1解题思路:首先二分查找分为左闭右闭和左闭右开两种情况,二种情况在细节处理上有所不同 2左闭右闭情况 3左闭右开 4总结: 1解题思路:首先二分查找分为左闭右闭和左闭右开两种情况,二种情况在细…

Go-知识sync map

Go-知识sync map 1. 用法1.1 声明1.2 增删改查1.3 增强操作 2. sync map 使用注意2.1 多读少写2.2 类型安全风险2.3 不能拷贝和传递 3. 实现原理3.1 数据结构3.2 read表数据结构3.3 entry 的数据结构3.4 sync map 的结构图3.5 插入数据3.6 查找数据3.7 再次插入3.8 删除数据 4.…

Unity基础学习

目录 基础知识点3D数学——基础Mathf三角函数坐标系 3D数学——向量向量模长和单位向量向量的加减乘除向量点乘向量叉乘向量插值运算 3D数学——四元数为何使用四元数四元数是什么四元数常用方法四元数计算 MonoBehavior中的重要内容延迟函数协同程序协同程序原理 Resources资源…

谁用过腾讯云轻量应用服务器2核2G3M配置,支持多少人在线?

腾讯云轻量应用服务器2核4G5M配置一年优惠价165元、252元15个月、三年756元,100%CPU性能,5M带宽下载速度640KB/秒,60GB SSD系统盘,月流量500GB,折合每天16.6GB流量,超出月流量包的流量按照0.8元每GB的价格支…

uniapp实现点击标签文本域中显示标签内容

先上一个效果图 实现的效果有: ①.点击标签时,标签改变颜色并处于可删除状态 ②.切换标签,文本域中出现标签的内容 ③.点击标签右上角的删除可删掉标签,同时清除文本域中标签的内容 ④.可输入内容,切换时不影响输入…

系统设计学习(三)限流与零拷贝

七、有哪些常用限流算法? Leaky Bucket 漏桶 漏桶可理解为是一个限定容量的请求队列。想象有一个桶,有水(指请求或数据)从上面流进来,水从桶下面的一个孔流出来。水流进桶的速度可以是随机的,但是水流出桶…

蓝桥杯小白赛第 7 场 3.奇偶排序(sort排序 + 双数组)

思路:在第一次看到这道题的时候我第一想法是用冒泡,但好像我的水平还不允许我写出来。我又读了遍题目发现它的数据很小,我就寻思着把它分成奇偶两部分。应该怎么分呢? 当然在读入的时候把这个问题解决就最好了。正好它的数据范围…

前端项目(vue3)自动化部署(Gitlab CI/CD)

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

C语言练习题【复试准备】

1、BoBo教KiKi字符常量或字符变量表示的字符在内存中以ASCII码形式存储。BoBo出了一个问题给KiKi,转换以下ASCII码为对应字符并输出他们。 //73,32,99,97,110,32,100,111,32,105,116,33 int main() {int arr[] {73,32,99,97,110,32,100,111,32,105,116,33};int i …

Swift:.ignoresSafeArea():自由布局的全方位掌握

ignoresSafeArea(_ regions : edges:)修饰符的说明 SwiftUI布局系统会调整视图的尺寸和位置,以避免特定的安全区域。这就确保了系统内容(比如软件键盘)或设备边缘不会遮挡您的视图。要将您的内容扩展到这些区域,您可以通过应用该修…

一文看懂红帽认证含金量有多高!

近期好多人来问红帽认证,有些是还在校的大学生,有些是已经工作的运维小伙伴。!现在的就业和职场环境下,系统学Linux确实是非常必要的。今天就给大家详细介绍下红帽认证,看看它的含金量有多高! 红帽认证是什么?红帽认证等级?红帽…

Sublime查看ANSI编码文档乱码问题

原因为没有安装对应的解码插件。 选择安装插件包 选择插件包:ConvertToUTF8或者GBK,我试了第一个插件包不行,安装GBK插件包后OK。