在我之前关于 docker
网络的文章中,我介绍了使用 docker CLI
进行网络管理的基础知识。但在现实生活中,你可能不会以这种方式工作,你将通过 docker-compose
配置来编排所需的所有容器。
这就是本文的用武之地 - 让我们看看如何在现实生活中使用网络。涵盖使用 docker-compose
进行网络管理的基础知识、如何将网络用于多存储库/多 docker-compose
项目、微服务以及如何利用它们来测试不同的问题场景,如有限的网络吞吐量、丢失的数据包等。
让我们从一些非常基本的东西开始,如果你已经熟悉 docker-compose
,你可能想要跳过下面的一些部分。
Docker-compose 基础知识
使用 docker-compose
开放端口
你可能想要做的第一件事就是简单地开放一个端口:
1 | version: "3.6" |
对于刚接触 Docker
的人来说,暴露意味着向外界开放一个端口。你可以通过 IP
限制它,但默认情况下,这意味着每个人都可以访问它。端口暴露在你的网络接口上,而不是容器接口上。在上面的例子中,你可以在端口 8080(localhost:8080)上访问 PhpMyAdmin 容器的端口 80。
如你所见,这非常简单,你只需传递要暴露的端口,遵循与 docker CLI
中相同的想法,即 localPort:containerPort。添加本地端口的监听接口显然也是可能的:
1 | version: "3.6" |
当你不想将某些服务暴露给外部时,这可能会很方便。
在 docker-compose 文件中连接容器
正如 docker
网络文章中提到的,docker-compose
默认创建一个网络。你可以通过创建一个非常简单的 docker-compose
配置文件轻松检查这一点:
1 | version: "3.6" |
让我们运行它并看看会发生什么:
1 | docker-compose up -d |
你可能在第一行就注意到了,为该项目创建了一个名为 myexampleproject_default 的默认网络。它在 docker CLI
中也可见:
1 | docker network ls |
此 docker-compose.yaml
中的所有容器都与此网络连接。这意味着,它们可以轻松相互通信,并且主机可以通过名称解析:
1 | docker-compose exec phpmyadmin bash |
Docker-compose 网络和面向微服务的架构
在编写面向微服务的项目时,能够在开发环境中模拟至少一部分生产方法非常方便。这包括分离和连接容器组,以及测试网络延迟问题、连接问题等。
将容器划分为单独的网络
但是,如果你不希望容器能够相互通信怎么办?也许你正在编写一个系统,其中一个部分应该对另一个部分隐藏?
实际上,系统的这些部分是使用 AWS VPC 或类似机制分离的,但在开发机器上测试它会很好,对吗?
没问题,让我们看看这个配置文件:
1 | version: "3.6" |
如你所见,我们有两个独立的服务,每个服务都包含一个 web 和 db 容器。我们希望仅从其 web 服务访问 db,因此 service2-web 无法直接访问 service1-db。
现在让我们检查一下它是如何工作的:
1 | docker-compose exec service1-web ash |
不幸的是,这些服务并没有按照我们所希望的方式分开。
不用担心,只需添加非常简单的更改即可实现:
1 | version: "3.6" |
我们引入了三个不同的网络(第 31-33 行)——每个服务一个,Web 服务共享一个。为什么我们需要第三个网络?这是允许 service1-web 和 service2-web 之间通信所必需的。我们还为每个服务添加了网络配置(第 7-8、13-15、20-21、26-28 行)。
现在让我们检查一下 service1-web 如何解析名称:
1 | dco exec service1-web ash |
如你所见,我们可以通过引入网络并仅将选定的容器连接在一起,轻松实现容器之间的分离。
在多个 docker-compose 文件之间连接容器
通常,上述项目会拆分到 git
存储库之间,或者至少拆分到 docker-compose.yaml
文件之间。因此,开发人员可以单独启动每个服务。我们如何连接这些服务?让我们来看看。
假设我们决定将之前使用的项目拆分为两个单独的存储库。一个用于 service1,另一个用于 service2。这意味着我们有两个 docker-compose.yaml
文件:
1 | #service1/docker-compose.yaml |
1 | #service2/docker-compose.yaml |
如果我们启动这两个配置,service1-web 和 service2-web 将无法相互通信,因为它们将被添加到两个不同的网络:每个 docker-compose.yaml 文件默认创建自己的网络。
1 | docker-compose up -d |
让我们首先重新添加 service1 的网络配置并进行一些小的修改:
1 | version: "3.6" |
我们在第 20 行添加了一些配置。在本例中,我想为我的 Web 网络指定一个固定名称。默认情况下,名称由 PROJECTNAME_NETWORKNAME 组成,项目名称默认为目录名称。我们所在的目录可能对不同的开发人员有不同的名称,因此安全的选择是强制使用这个名称。
现在,对于 service2,我们需要采取一些不同的行动:
1 | version: "3.6" |
如你在第 20-21 行中看到的,在本例中我们配置了一个外部网络。这意味着,docker-compose 不会尝试创建它,如果不可用,它将失败。但是一旦可用,它就会重新使用它。
就是这样。Service1 和 2 Web 容器可以相互访问,但它们的数据库是分开的。两者也可以在单独的存储库中开发。
作为上述内容的扩展,你可以查看容器别名以使路由更容易,或者内部路由以进一步隔离服务。
混沌测试
如你所知,当发生中断时,问题不是是否会发生,而是何时发生。最好为这种情况做好准备,并测试系统在出现不同问题时的行为。
如果某些数据包丢失或延迟增加,会发生什么?也许服务离线?
混沌测试就是为此做好准备。
我强烈建议你查看 Pumba
,这是一个允许你暂停服务、终止服务的项目,但也会添加网络延迟、丢失、损坏等。
完整描述 pumba
需要大量时间,所以让我们只看一个非常简单的网络延迟模拟。
让我们启动一个 ping 8.8.8.8 的容器:
1 | docker run -it --rm --name demo-ping alpine ping 8.8.8.8 |
现在,查看输出,在单独的控制台选项卡中运行以下命令:
1 | pumba netem --duration 5s --tc-image gaiadocker/iproute2 delay --time 3000 demo-ping |
就这样!
你还可以在几分钟内实施其他混沌测试。
总结
Docker
和 docker-compose
是模拟不同网络配置的绝佳工具,无需设置服务器或虚拟机。命令和配置非常容易使用。结合 Pumba
等外部工具,你还可以测试问题情况并为中断做好准备。
相关文章: