语境:
我正在使用 Circle CI 的aws-ecs/deploy-service-update
orb 来部署我的 docker 容器,方法是从 AWS ECR 中提取最新映像并将其部署到具有 AWS EC2 实例的 AWS ECS 中。此容器是一个机器学习模型,它接受 TCP 端口 3000 的 API 请求(我正在使用fastAPI
它)并返回预测。部署它后,我无法向在端口 3000 部署容器的任务的容器实例的公共 IP 发送请求(此 IP 不是我的 EC2 实例的公共 IP;它只有私有 IP,并且公共 IP 已禁用)。
调试
- 我检查了我的安全组,并确保端口 3000 已开放以接收来自所有 IP(0.0.0.0)的请求,作为入站规则的一部分。
- 我停止了该任务(这将自动停止在 EC2 实例中运行的容器),因为我认为 Circle CI 可能出了问题。然后,根据 AWS ECS 的服务配置(1 个所需任务)和任务定义,一个新任务(因此是容器)已自动启动。但是,我也无法向其发送请求。
- 我通过 SSH 连接到我的 EC2 实例,以了解端口 3000 是否打开。这时我才发现端口根本没有映射:
如您所见,容器的 PORTS 列为空,并且容器必须接受来自命令的端口 3000 的请求。
以下是 EC2 实例的开放端口: 如您所见,端口 3000 没有列在这里。
以下是部署容器(到 AWS ECS)的端口映射任务,如docker ps
上面的屏幕截图所示:
在任务定义中,您可以看到我为容器定义的端口映射。
这是在我的 EC2 实例上运行的任务,其任务定义如上所示,我使用的网络模式是“awsvpc”:
这是与任务关联的 ENI 的“网络”选项卡,也是与任务在其中运行的 EC2 实例关联的安全组的入站规则,它接受来自所有 IP 的端口 3000 上的请求。
编辑1:
在我这样做之后
docker run -p 3000:3000 <my-image:my-tag>
在 EC2 机器内部(通过从我的笔记本电脑进行 SSH 连接),我可以向容器发送 API 请求并接收对容器的正确响应,该容器是 AWS ECS 集群的公共 IP。这意味着仅当我手动运行容器时才会映射端口。
当我使用 FARGATE 时,当我从 Circle CI 更新服务时,甚至当我手动启动任务时,端口都没有问题。
那么,当从 AWS ECS 服务仪表板或 Circle CI 运行任务时,如何自动映射端口?如果我手动运行 Docker 容器,我将无法从 AWS Cloudwatch 自动获取日志,也无法从 AWS ECS 仪表板停止它。在 EC2 实例中运行的另一个 AWS 容器将负责这些事情。它会将日志路由到 Cloudwatch 并接受停止现有容器并启动命令以启动一个新容器,新容器的新映像存储在 AWS ECR 中,而不必每次想要查看日志或启动/停止容器时都使用 SSH。
这里出了什么问题,导致端口无法映射,我该如何修复它并正确映射端口,以便我能够将 API 请求发送到我的容器。
答案1
由于您正在使用网络模式:awsvpc容器将拥有自己的 IP 地址,不会使用 EC2 实例的 IP。您可以在正在运行的任务详细信息中找到容器的 IP。
或者你可以使用网络模式:主持人其中该任务将共享 EC2 实例的 IP,并可通过实例 IP 端口 3000 访问。
希望有帮助:)
答案2
在阅读了大量博客页面后,我发现如果你想使用特权端口,那么你需要将 AWS 中的网络模式更改为桥。
或者您可以使用负载均衡器来映射端口。
希望这个答案有帮助:)