繁体   English   中英

如何从我的前端容器访问我的 Docker API 容器?

[英]How do I access my Docker API container from my front-end container?

我是 docker 的新手,并试图围绕容器之间的网络进行思考。 我正在运行两个容器,一个用于我的 Node.js API 服务器的容器,一个用于保存我的前端 React UI 的容器。 在本地运行它们时一切正常。 API 服务器公开端口 3001,我可以从我的 React 站点调用 localhost:3001/api。

鉴于容器的想法是它可以在任何地方运行,我如何保证这两个容器服务在不在本地机器上运行时可以连接? 我知道可以在 docker 容器之间设置网络,但这在这种情况下似乎不适用,因为 react 容器没有发出请求,而是客户端访问 react 容器(因此 localhost 现在指的是他们的机器而不是我的 API 容器)。

部署此类架构的最佳实践是什么?

需要什么样的设置才能保证这些容器可以在部署时动态生成 API 主机的云部署中进行通信?

如果相关,我特别希望部署到 AWS ECS。

编辑:

package.json 代理仅与开发相关,因为该代理在 React 应用程序的生产版本中不起作用。

据我了解,您希望将一个由 React 前端和 Node.js 后端组成的经典两层应用程序部署到 Amazon ECS(生产环境)。

我们前段时间为我们的应用程序设置了这个,我想概述解决方案。

部署此类架构的最佳实践是什么?

这是一个非常棘手的问题,因为它还取决于您的问题中未完全指定的两层的某些特征。

前端

我想到的第一个问题是,您是否真的需要从 docker 容器运行 React UI? 是动态内容吗? 如果你的 React 应用程序是为生产而构建的——如 [1] 中所述——它应该是静态内容。 静态内容的优势在于,它可以轻松缓存,因此不需要从生产中的 Docker 容器提供服务。 情况恰恰相反:我认为在生产中从 ECS 容器提供静态内容是一种不好的做法。 你应该做的是:

  • 创建一个 S3 存储桶并将您的静态资产部署到该存储桶中。
  • 可选,但强烈建议用于生产:使用某种内容交付网络 (CDN) 来分发您的内容并将其有效地缓存在边缘。 AWS 服务环境为此提供了 CloudFront 服务。 使用 CloudFront 是否值得反过来取决于您的应用程序的流量模式。 您可以直接从 S3 存储桶中提供静态资产,这可能会导致更高的延迟,但可能更具成本效益。

总而言之,我建议:如果您计划将一些严肃的应用程序投入生产,这些应用程序预计会收到大量流量和/或被设计为单页应用程序 (SPA),请将您的静态资产外包到 S3 中并为它们提供服务通过 CloudFront

后端

此处的最佳实践很简单:创建应用程序负载均衡器 (ALB)、目标组并将您的目标组指向您的 ECS 服务。 ECS 为 AWS Elastic Load Balancing 提供集成。 在这里使用 AWS ALB 的优点是会自动为您创建 DNS 记录。 [3]

但是如果我真的需要在 ECS 中使用两个容器呢?

如果您决定不外包静态资产,因为您的 React 内容中有动态部分,或者上述解决方案的定价不合适,让我回答您的第二个问题:

需要什么样的设置才能保证这些容器可以在部署时动态生成 API 主机的云部署中进行通信?

在 ECS 中如何将事物连接在一起有多种策略。 我猜你的 React 容器不需要直接连接到 Node.js 容器,对吧? 如果这个假设是错误的,请纠正我。 对我来说,场景如下所示:

  1. 客户端 --> Docker 容器 1 “React”(加载例如 index.html)
  2. 客户端(例如在 index.html 中使用 Ajax)--> Docker 容器 2“Node.js”

如果这两层真的完全独立,我建议创建两个单独的 ECS 服务 - 每个运行一个单独的 ECS 任务定义 其次,您创建一个应用程序负载均衡器并在每个服务上激活负载均衡器集成。 最后,您需要在负载均衡器上为每个服务创建一个单独的目标组,并在负载均衡器上分配一个单独的侦听器以将流量重定向到相应的目标组。

例子:

  • 具有 DNS 名称的应用程序负载均衡器:my-loadbalancer-1234567890.us-west-2.elb.amazonaws.com
  • 带有 React 前端的服务 A
  • 带有 Node.js 后端的服务 B
  • 将流量重定向到服务 A 的目标组 A
  • 将流量重定向到服务 B 的目标组 B
  • ALB 侦听器 A,它将负载均衡器的端口 80 上的流量重定向到目标组 A
  • ALB 侦听器 B 将负载均衡器端口 8080 上的流量重定向到目标组 B
  • 可选:您自己域的自定义 DNS 记录,它指向负载均衡器(通过别名记录),以便在浏览器中提供对客户更友好的名称,而不是在 aws 区域elb.amazonaws.com 中自动创建的记录.

现在前端可通过负载均衡器域的标准 HTTP 端口访问,后端可通过端口 8080 访问。您可以轻松地在负载均衡器上激活 SSL,并改用端口 443。 [4]
这允许 SSL 在负载均衡器上终止,而不是在您的 docker 容器上终止——这一特性称为 SSL 终止 [5]。

但是如果这些容器必须相互通信呢?

通过上述方法,容器能够通过应用程序负载均衡器相互通信。 但是,如果此通信本质上是内部通信,则这并不理想,因为它是通过公共负载平衡器端点路由的。 如果我们想确保流量不会离开容器之间的专用网络,我们可以*将它们放在一起:

  • 在 ECS [6] 中创建任务定义并将两个容器放入其中
  • 为任务指定"NetworkMode": "bridge"
  • 使用各自容器定义上的属性Links指定容器之间的Links (在任务定义内)

*再次有多种策略可以实现这一点,我在这里概述了我所知道的最简单的一种(例如,也可以使用服务发现 [7] 或任务网络模式awsvpc将任务私下链接在一起)

我知道这是一个复杂且特别广泛的话题,因为有多种策略,每种策略都有其优缺点,但我希望我能给你一些有用的参考。

参考

[1] https://create-react-app.dev/docs/production-build/
[2] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-load-balancing.html
[3] https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-creating.html#resource-record-sets-elb-dns-name-procedure
[4] https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html
[5] https://infra.engineer/aws/36-aws-ssl-offloading-with-an-application-load-balancer
[6] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-task-definition.html
[7] https://stackoverflow.com/a/57540515/10473469

先说第一件事。 由于 Node.js API 服务器和前端 React UI 都运行在两个不同的容器上,因此您需要在 React 应用程序的package.json中配置代理。

"proxy": "http://<docker_container_name>:3001",

如果您仍然想知道这个代理是什么,为什么需要它,请在进一步阅读之前参考内容。

现在因为我们的服务在两个不同的容器中运行,所以"proxy": "http://localhost:3001",将不起作用,因为这会在同一个前端容器中代理请求。 因此,我们需要告诉反应服务器将请求代理到在其他容器上运行的节点服务器。

因此, docker_container_name实际上是运行 Node.js API 服务器的docker容器名称。

"proxy": "http://<docker_container_name>:3001",

注意:确保在 Node 服务器容器中公开端口 3001。

如果不想暴露节点服务器的端口怎么办??

为此,我建议使用 docker-compose。 创建一个docker-compose.yml看起来像这样:

version: "3.7"
services:
  frontend:
    # Add other configuration options for frontend service
    depends_on:
      - backend  
  backend:
    # Add configuration options for backend service

请参阅以了解有关depends_on的更多信息

在这种情况下似乎不适用,因为反应容器没有发出请求,而是客户端访问反应容器

我对 React UI 的经验不是很丰富,但是如果我错了,请纠正我,据我所知,客户端浏览器首先连接到 React UI 前端,后者反过来提供(或响应)具有功能的网页使用嵌入式基本 url 将 API 请求发送到 Node.js API 服务器,并且它正在侦听端口 3001。在这种情况下,在我看来,React UI 前端容器没有连接到 Node.js API 容器,它只是为客户端浏览器提供方法,让网页将请求发送到正确的位置。

虽然我觉得package.json中的proxy似乎是关键,但这又不是我的专业领域,真正需要做的是配置 React UI 容器以在托管 Node JS API 的地方嵌入正确的主机名客户端浏览器会将请求发送到正确的目的地。 考虑到您可以在本地机器上执行的操作,在我看来,您的容器的端口配置已正确完成,我将假设它们正在“暴露”。 因此,在具有 docker 的服务器上以相同的方式运行容器也将正确公开端口。

所以总结一下,你基本上会有一个服务器,它有一个公共主机名,并在上面运行 docker,它反过来会运行你的容器并公开它们的端口。 所需的基本配置是让 React UI 容器提供 Node.js API 的正确 URL,该 URL 实际上将是您服务器的公共主机名(因为 docker 在技术上侦听服务器上的端口并将它们发送到容器内,这就是公开的意思,更像是端口转发)。

你必须准备一个最小的 VPC。 一个子网(路由表、网关、负载均衡器等)。 VPC 和子网将配置一个 IP 范围。

子网中的所有实例都会获得超出其范围的 IP,并且您的应用程序实例可能会相互通信。 您可以为您的应用预设固定 IP。

关于蓝/绿部署,需要实例化(Fargate)ECS 集群。 docker 容器对应的 AWS 服务是 AWS ECR。 我建议使用 AWS Fargate 而不是纯粹的 AWS ECS 实例——更少的钱,更多的灵活性。

关于 VPC 和子网的信息: https : //docs.aws.amazon.com/AmazonECS/latest/userguide/create-public-private-vpc.html

Fargate 和集群信息: https ://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-cli-tutorial-fargate.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM