写点什么

【Docker 那些事儿】容器网络(上篇)

  • 2022 年 7 月 16 日
  • 本文字数:4152 字

    阅读完需:约 14 分钟

【Docker 那些事儿】容器网络(上篇)

🌟 前言

当企业开始大规模使用 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 服务。


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

发布于: 刚刚阅读数: 4
用户头像

🏅️ InfoQ 专家博主 2022.03.08 加入

CSDN:飞向星的客机

评论

发布
暂无评论
【Docker 那些事儿】容器网络(上篇)_Docker_飞向星的客机_InfoQ写作社区