面向初学者的简单 ECS + ECR 项目
您是 AWS 新手,正在尝试了解 ECS 和 ECR 如何协同工作来部署应用程序吗?这篇文章正是为您准备的!在本篇简单的演练中,我们将学习如何将应用程序容器化,将镜像存储在 Amazon ECR 中,并使用 Terraform 在 ECS 上运行它。
✅ 先决条件
开始之前,请确保已安装并配置以下内容:
- ✅ AWS CLI(已配置凭证)
- ✅ Terraform
- ✅ Docker
- ✅ 一个现有的 ECR 存储库(或者 Terraform 可以为您创建一个)
🧰 本项目中使用的服务(基于 Terraform)
1. Amazon ECR(弹性容器注册表)
🗃️ 一个完全托管的 Docker 容器注册表,用于存储和管理您的容器镜像。
- 用于存储由您的应用程序构建的 Docker 镜像。
- Terraform 可以自动创建(或重用)ECR 存储库。
- ECS 服务在运行时直接从 ECR 拉取镜像。
2. Amazon ECS(弹性容器服务)与 Fargate
🚢 容器编排服务,可让您运行和扩展容器化应用程序。
- 我们使用 Fargate,一种无服务器计算引擎,它消除了管理 EC2 实例的需要。
- ECS负责容器的部署、扩展和管理生命周期。
- 一个或多个 ECS 任务(容器)在由集群支持的 ECS 服务中运行。
3. 亚马逊 VPC(虚拟私有云)
🌐 所有 AWS 资源均部署在隔离的网络环境中。
- 为 ECS 服务和 ALB 配置了带有公共子网的自定义 VPC。
- 包括互联网网关、路由表和安全组。
- 为您的应用提供安全有序的网络边界。
4. 应用负载均衡器(ALB)
⚖️ 将传入流量分配到在不同可用区运行的 ECS 任务中。
- 通过HTTP协议公开您的应用程序。
- 自动将流量分配到可用的 ECS 容器(目标)。
- 集成 CloudFront 作为源。
5. Amazon CloudFront(内容分发网络)
🚀 安全快速地将您的内容送达全球各地。
- 位于 ALB 前面,缓存静态和动态内容。
- 默认使用 AWS 管理的 SSL 证书提供 HTTPS 服务。
- 与 S3 集成以存储访问日志,并与 CloudWatch 集成以进行监控。
6. Amazon S3(简单存储服务)
💾 安全、耐用的对象存储,适用于任何类型的数据。
- 用于存储 CloudFront 访问日志,从而可以了解谁在何时以何种方式访问了什么。
- 系统会自动创建一个专用存储桶来收集日志。
- 可用于调试、审计和流量分析。
7. Amazon CloudWatch
📈 用于 AWS 资源和应用程序的监控和可观测性平台。
- 跟踪关键的 CloudFront 指标,例如请求计数、4xx/5xx 错误率和延迟。
- 用于触发警报和分析性能趋势。
- 如果已配置,还可以记录自定义应用程序或 ECS 级别的日志。
8. Amazon SNS(简单通知服务)
🔔 用于根据监控触发器发送通知的消息服务。
- 已连接至 CloudWatch 警报,用于发送电子邮件通知。
- 当超出阈值时发出警报(例如,CloudFront 出现过多 5xx 错误)。
- 确保您能立即收到有关潜在问题或流量高峰的通知。
9. Terraform
🛠️基础设施即代码工具,用于自动化和管理所有云资源。
- 在不同环境中一致地定义、配置和销毁基础设施。
- 实现 VPC、ECS、ALB、CloudFront、S3、CloudWatch 和 SNS 设置的完全自动化。
- 使您的部署可重复、版本可控且易于维护。
🛠️部署步骤
步骤 1:初始化 Terraform
在您的工作目录中设置 Terraform。
terraform init
步骤 2:格式化 Terraform 代码
清理 Terraform 文件(可选,但推荐):
terraform fmt
步骤 3:准备 Docker 镜像并推送到 ECR
如果您尚未将应用程序镜像推送到 ECR,请检查ecr_push.sh脚本文件夹并运行以下命令
。此脚本将执行以下操作:
- 构建 Docker 镜像
- 用你的 ECR 存储库 URL 标记它
- 将图像推送到 ECR
⚠️ ECR 中已有图片?您可以跳过此步骤。
✅ 部署前的最终检查
🔍 1. 仔细检查 Terraform 变量配置
确保以下内容已正确定义并填充:
在 variables.tf 中:
- 地区
- ECR存储库名称
- S3 日志存储桶名称(可选的默认名称或动态名称)
- CloudFront 价格类别或别名配置(如有)
- SNS 主题订阅电子邮件
- 为确保安全,限制对特定 IP 地址的访问(请查看 VPC 模块 main.tf 文件)
- ECS 任务内存、CPU 和任务数量
- 日志保留期
步骤 4:查看 Terraform 计划
预览 Terraform 将创建的内容:
terraform plan -out=tfplan
忽略 1 以销毁
步骤 5:应用 Terraform 配置,
部署基础架构:
terraform apply tfplan
或者简单地说:
如果你在 Terraform Plan 命令中不使用 -out=tfplan 参数,
terraform apply
运行期间,您会收到一封订阅邮件,我已将其用于社交媒体主题。点击并确认订阅。
由于 Terraform 需要配置多个资源,例如 ECS 任务、服务、ALB 和 CloudFront,因此部署可能需要几分钟时间。
默认情况下,Terraform 会通过分析其内部依赖关系图来确定资源的创建顺序。
但是,如有需要,我们可以使用 depends_on 属性显式地控制创建顺序。
您可以忽略此消息——Terraform 正在尝试重新创建 ECR 镜像,但由于该镜像已存在,因此没有必要重新创建。为了避免将来再次出现这种情况,您可以使用 Terraform 生命周期规则来ignore_changes阻止对镜像配置的更新。
✅ 第 6 步:访问您的应用程序
Terraform 创建完所有资源后,会自动生成一个 outputs.txt 文件,其中包含部署的关键访问信息。
感谢 main.tf 中的 null_resources 代码块
此文件包含:
- VPC ID
- ECR Repository URL
- ECS Cluster Name
- Load Balancer DNS
- CloudFront Domain Name
- CloudWatch Dashboard Name
- S3 Logs Bucket Name
- SNS Topic ARN
⚠️ 如果实际项目中包含敏感数据,请确保不要将 outputs.txt 提交到版本控制系统中。
或者运行命令
terraform output
您可以使用任一 URL 访问您的 Web 应用程序。
🔗 应用网址:
- CloudFront(全局 HTTPS):推荐用于生产环境
- ALB DNS(直接 HTTP):适用于内部测试或快速验证
步骤 7:清理资源
完成后,销毁所有已创建的 AWS 资源以避免产生费用:
terraform destroy
⚠️ 关于销毁资源的注意事项:
在执行 `terraform destroy` 命令时,大多数 AWS 资源将自动删除。但是,您可能会看到类似这样的错误:
ECR Repository not empty – cannot delete
S3 Bucket not empty – cannot delete
这是因为:
- 如果 Amazon ECR 中仍包含图像,则不允许删除。
- 如果 Amazon S3 中包含对象/日志,则不允许删除。
✅ 解决方案
🔹 选项 1:通过 AWS 控制台手动删除
转到 ECR → 选择您的存储库 → 删除所有图像。
前往 S3 → 选择存储桶 → 清空存储桶 → 然后删除它。
🔹选项2:使用AWS CLI
删除所有ECR镜像:
aws ecr batch-delete-image \
--repository-name ecs-ecr-demo \
--image-ids $(aws ecr list-images --repository-name ecs-ecr-demo --query 'imageIds[*]' --output json)
清空并删除 S3 存储桶:
aws s3 rm s3://ecs-ecr-demo-logs-<your-bucket-id> --recursive
aws s3 rb s3://ecs-ecr-demo-logs-<your-bucket-id>
清除这些问题后,重新运行:
terraform destroy
🔁 流程概要
- 用户发送请求 → CloudFront 通过 HTTPS 接收请求。
- CloudFront 检查缓存;如果缓存未命中,则转发到 ALB。
- ALB 将请求转发给 ECS 任务之一(Fargate)。
- ECS 任务(运行 NGINX)返回响应。
- CloudFront 会缓存响应并将响应发送回用户。
- 日志上传至 S3;指标上传至 CloudWatch;警报(如有)通过 SNS 发送。
🎨 设计选择
模块化 Terraform 结构:
- 每个组件(VPC、ECS、ECR、ALB、CloudFront)都在各自的模块中。
- 易于扩展、维护或重复使用。
- 无状态 Web 应用:
- 一个简单的基于 NGINX 的静态页面,用于演示目的。
- 安全:
- 用于快速演示访问的公共子网。
- 安全组将流量限制在端口 80 和 443 以内。
输出文件:
null_resource 会将重要信息(例如 URL、VPC ID)写入 outputs.txt。
🔧 如何自定义
- 📝 修改 docker/index.html 文件以更新网站内容
- 🏗️ 编辑 main.tf 文件以修改基础架构行为
- 🔁 更新 ECS 模块以更改容器设置
💡小贴士
- 在 ECR 模块中添加 lifecycle { ignore_changes = [...] } 以避免重新创建问题。
- 当您需要手动控制资源顺序时,请使用 depends_on。
- 对于实际应用,请考虑使用私有子网、ALB 上的 HTTPS 和自定义域名。
🚀 立即体验
📦 GitHub 代码库:https://github.com/aquavis12/ecs-ecr-demo
文章来源:https://dev.to/aws-builders/a-simple-ecs-ecr-project-for-beginners-4gc0









