(文章目录)

🌟 前言

当企业开始大规模使用 Docker 时,工程师就需要掌握很多关于网络的知识。   Docker 作为目前流行的轻量级容器技术,有很多令人称道的功能,如前面介绍的 Docker 镜像管理。   然而,Docker 也有很多不完善的地方,网络方面就是 Docker 比较薄弱的部分。   作为初学者的我们来说很有必要深入了解 Docker 的网络知识,以适应更高的网络需求。

1. 容器网络概述

🍑 容器网络概述

容器网络主要用于容器与容器、容器与外网、容器与宿主机之间的通信及互联。

宿主机接通外网,再与容器之间搭建网桥,使容器与宿主机网络联通,以达到容器连接外网的目的,如图所示👇 在这里插入图片描述 用户可以创建一个或多个网络,一个容器可以加入一个或多个网络。

同一个网络中的容器可以相互通信,不同网络中的容器相互隔离。

在创建容器之前,用户可以先创建网络,然后再将容器添加到网络,即创建容器与创建网络是分开的。

Docker 的本地网络实现是利用了 LinuxNetwork Namespace 和虚拟网络设备(主要是 Virtual Ethernet Pair),在本地主机和容器内分别创建一个虚拟接口,并使它们彼此连通。

Docker 使用 LinuxNamespace 技术来进行资源隔离,例如,PID Namespace 隔离进程、Mount Namespace 隔离文件系统、Network Namespace 隔离网络等。

Network Namespace 为容器提供了独立的网络环境。

Virtual Ethernet Pair 简称 VETH Pair,是一对端口,所有从这对端口进入的数据包都将从另一端出来,反之也是一样。

🍑 查看容器网络

用户要对容器网络进行配置,首先要熟练掌握命令,下面详细介绍容器网络管理命令。

查看容器网络的命令格式为: 在这里插入图片描述 参数介绍如下👇

  • -f--filter filter

过滤条件。

  • --format string

格式化打印结果。

  • --no-trunc

不缩略显示。

  • -q--quiet

只显示网络对象的 ID

首先,查看所有容器网络,示例代码如下: 在这里插入图片描述 如以上示例所示,容器网络也有其固定的 ID 号,DRIVER 表示容器网络的驱动程序,SCOPE 表示容器网络的作用域。

默认情况下,容器创建完成后,会自动创建 bridgehostnone 三种网络模式。

接着,通过在命令中添加过滤条件查看容器网络,示例代码如下: 在这里插入图片描述 以上示例通过 -f 参数添加了 'driver=host' 过滤条件,成功过滤出了 host 网络。

通常 Docker 所显示的容器 ID 号、镜像 ID 号等都是通过缩略之后的结果,只要在命令中添加对应的参数即可显示完整 ID 号。

通过在命令中添加参数,以不缩略的形式列出所有容器网络,示例代码如下: 在这里插入图片描述 以上示例在命令中添加了 --no-trunc 参数,以不缩略的形式列出了所有容器网络。

最后,通过在命令中添加参数,列出所有网络的 ID 号,示例代码如下: 在这里插入图片描述 以上示例在命令中添加了 -q 参数,列出了所有容器网络的 ID 号。

🍑 创建容器网络

创建网络的命令格式为: 在这里插入图片描述 参数介绍如下👇

  • -d--driver string

指定网络模式(默认为bridge)。

  • --subnet strings

指定子网网段。

  • --ip-range strings

指定容器的IP地址范围,格式同subnet参数。

  • --gateway strings 子网的 IPV4IPV6 网关。

创建一个容器网络,并指定它的网络模式,示例代码如下: 在这里插入图片描述 以上示例创建了一个命名为 test-bridge 的新容器网络,并指定它的网络模式为 bridge 网络。

其余网络属性配置方式与之相同,这里不再赘述。

🍑 删除容器网络

下面将讲解删除容器网络的操作,在生产环境中建议再三确认之后再执行删除操作。

删除容器网络与删除容器同样都需要在命令中添加 rm 参数。

删除容器网络的命令格式为: 在这里插入图片描述 首先,查看是否有需要删除的容器网络,示例代码如下: 在这里插入图片描述 接着,将需要删除的容器网络进行删除,示例代码如下: 在这里插入图片描述 最后,查看容器网络是否被删除,示例代码如下: 在这里插入图片描述 从以上示例中,可以看到容器网络 test-bridge 已经成功删除。

🍑 容器网络详细信息

查看容器网络详细信息的命令格式为: 在这里插入图片描述 参数介绍如下👇

  • -f--format string

使用给定的模板格式化输出。

示例代码如下: 在这里插入图片描述 以上示例查看了 none 网络的详细信息,包括容器网络名称、容器网络 ID 容器网络创建时间等。

🍑 配置容器网络

配置容器网络就是为用户创建的容器添加网络配置,只需要在运行容器的命令中添加指定的网络参数。

配置容器网络的命令格式为: 在这里插入图片描述 示例代码如下: 在这里插入图片描述 以上示例通过在运行容器中添加 --network 参数,指定了容器的 host 网络模式。

其中,反斜杠 "\" 表示命令没有输入完,上下两行为同一条命令,这种命令输入方式适合在输入长命令时使用。

下面查看容器信息,验证该容器网络是否为 host 模式,示例代码如下: 在这里插入图片描述 以上示例通过 docker inspect 命令中添加 grep 参数过滤出了该容器的网络模式为 host 的信息。

下面运行一个不指定网络模式的容器,并查看其网络模式信息,示例代码如下: 在这里插入图片描述 由以上示例可见,不指定网络模式,Docker 会默认使用 bridge 网络模式。

🍑 容器网络连接与断开

容器网络连接与断开的命令格式为: 在这里插入图片描述 下面通过示例讲解容器网络的连接与断开,首先创建一个容器,示例代码如下: 在这里插入图片描述 以上示例运行了一个连接 host 网络的容器。

然后将该容器与 host 网络断开,示例代码如下: 在这里插入图片描述 以上示例使该容器与 host 网络断开。

在命令中使用 ID 号即可,并且断开网络之前需要先关闭该容器。

下面再次执行断开网络命令,观察执行结果,示例代码如下: 在这里插入图片描述 以上示例中,再次执行断开命令时发生报错,提示网络已断开。

下面将该容器添加到 none 网络中,示例代码如下: 在这里插入图片描述 以上示例中,供执行了两次连接 none 网络的命令。

第一次执行命令使容器成功连接了 none 网络,再次执行命令连接时报错,提示容器已在 none 网络中。

2. none网络

顾名思义,none 网络就是什么都没有的网络。

在这种模式下,Docker 容器网络拥有自己的网络命名空间,但并不为 Docker 容器进行任何网络配置。

也就是说,这个模式下的容器除了本地环回接口,没有其他任何 网卡IP路由 等信息,如图所示👇 在这里插入图片描述 没有网络配置的情况下,Docker 开发者才能在此基础上做其他无限多可能的网络定制开发。

用户可以自己为 Docker 容器添加网卡、配置 IP 地址等。

这也正体现了 Docker 开放的设计理念。

下面使用默认网络模式创建一个 BusyBox 容器。示例代码如下: 在这里插入图片描述 以上示例运行了一个被命名为 test-defaultBusyBox 容器,并且此时已进入容器。

下面在容器终端中查看容器 IP 地址,示例代码如下: 在这里插入图片描述 从以上示例中可以看到,Docker 为容器分配了 IP 地址。

下面通过 ping 命令测试容器网络是否能够联通外网,示例代码如下: 在这里插入图片描述 以上示例中,通过 ping 协议连通了外网,说明容器能够正常上网,。

作为对比验证,再运行一个 BusyBox 容器,将网络设置为 none 模式,示例代码如下: 在这里插入图片描述 通过以上示例的对比验证,可以很清晰地理解 Docker 容器 none 网络就是没有网络。

没有网络意味着安全性非常高,这样的网络模式通常可以用在一些对安全性要求较高,并且不需要联网的应用中,如用来产生随机密码的应用。

3. host 网络

一个 Docker 容器一般会被分配一个独立的网络命名空间,但如果启动容器时选择了 host 模式,那么这个容器将不会分配一个独立的网络命名空间,而是和宿主机共享同一个网络命名空间。

容器将使用宿主机的 IP 地址和 端口号,如图所示👇 在这里插入图片描述 下面在宿主机上运行一个网络模式为 hostWeb 应用容器,示例代码如下: 在这里插入图片描述 上述示例运行了一个命名为 test-hostNginx 容器,并指定网络模式为 host,使其在后台运行。

下面查看容器信息,示例代码如下: 在这里插入图片描述 从以上示例中,可以看出网络模式为 host

下面再查看宿主机的 80 端口状态,示例代码如下: 在这里插入图片描述 从以上示例中可以看出 80 端口被 Nginx 进程占用。

创建容器时并没有指定端口映射,容器默认使用了宿主机的 80 端口,证明在 host 模式下宿主机与容器共用端口。

下面通过 curl 工具测试容器网站是否能够被访问,示例代码如下: 在这里插入图片描述 下面是浏览器的访问测试结果,如图所示👇 在这里插入图片描述

4. bridge网络

bridge 模式下,Docker 守护进程创建了一个虚拟以太网桥 Docker0,附加在其上的网卡之间能自动转发数据包。

默认情况下,守护进程会创建一对对等接口,将其中一个接口设置为容器的 eth0 接口,另一个接口 veth 放置在宿主机的命名空间中,从而将宿主机上的所有容器都连接到这个内部网络上。

同时,守护进程还会从网桥的私有地址空间中分配一个IP地址和子网给该容器。如图所示👇 在这里插入图片描述 下面通过 brctl show 命令可以查看容器网桥信息,在这之前需要安装网桥工具管理包,否则命令不生效,示例代码如下: 在这里插入图片描述 安装完成之后,即可查看容器网桥信息,示例代码如下: 在这里插入图片描述 下面运行一个网络模式为 bridge 的容器,示例代码如下: 在这里插入图片描述 以上示例在后台运行了一个命名为 test-nginxNginx 容器,并指定它的网络模式为 bridge,将宿主机的 8000 端口映射到了容器的 80 端口。

下面接着查看容器网桥信息,示例代码如下: 在这里插入图片描述从以上示例中可以看到,网桥 Docker0 上挂载了网络接口,vethaaf8a5e 就是新创建的 Nginx 容器的虚拟网卡,名称以 veth 开头。

下面运行一个 BusyBox 容器,并设置网络模式为 bridge,查看其网卡信息,示例代码如下: 在这里插入图片描述 上述示例中,veth70a4bee 就是 BusyBox 容器的虚拟网卡,名称同样以 veth 开头。

Docker 采用 NATNetwork Address Translation,网络地址转换)方式,将容器内部服务监听的端口与宿主机的某一个端口进行映射,使宿主机以外的网络可以将网络报文发送至容器内部。

访问容器时,需要访问宿主机的 IP 及端口。

因为增加了网络层,所以会影响网络的传输效率,如图所示👇 在这里插入图片描述 在同一个服务器中,可能运行着多个业务,若这些业务都使用默认端口将会产生冲突,这时就需要容器映射不同的端口。

下面在宿主机中安装 Apache 服务,示例代码如下: 在这里插入图片描述 安装完成之后,启动 Apache 服务,示例代码如下: 在这里插入图片描述 以上示例在宿主机中启动了一个 Apache 服务。

下面通过查看端口的形式验证 Apache 是否正常运行,示例代码如下: 在这里插入图片描述 以上示例查看宿主机 80 端口,可以看到 80 端口被 Apache 占用,服务正常运行。

下面创建一个 Nginx 容器,并配置端口映射,示例代码如下: 在这里插入图片描述 以上示例在后台运行了一个命名为 test-nginxNginx 容器,并将容器 80 端口映射到宿主机的 8000 端口。

下面测试用户通过宿主机的 8000 端口是否能够访问容器中的 Nginx 服务,示例代码如下: 在这里插入图片描述 从以上示例可以看出,通过宿主机的 8000 端口可以正常访问 Nginx 容器。

下面再访问宿主机的 Apache 服务,示例代码如下: 在这里插入图片描述 从以上示例可以看出,通过宿主机 80 端口可以正常访问 Apache 服务。

有了端口映射,容器与容器、容器与宿主机的业务就不会出现冲突,保证了业务都能够被正常访问。