site logo

Marico's space

在 AWS ECS Fargate 上部署 Docker 容器

服务器技术 2026-05-05 11:32:50 26

说到把应用跑在 AWS Fargate 上,我之前折腾过不少次。AWS 官方文档确实有点散落各地,很多教程也只教到"Hello World"就结束了,真正上线生产环境要的东西(HTTPS、自定义域名、负载均衡、自动扩缩容)基本都略过了。这篇文章把整个流程串了一遍,从把 Docker 镜像推到 ECR 到配好 CI/CD 流水线,30 分钟左右能搞定一个生产级别的部署。内容挺实在的,分享给大家。

你的应用已经用 Docker 容器化了。接下来呢?

如果用的是 Railway 或 Render 这种 PaaS(平台即服务),直接 git push 就行,剩下的平台帮你搞定。这种便利是真实的,但就像我们在《Vercel、Railway 和 Render 的隐性成本》里讨论的,同样的工作量跑在 AWS 上要多花 3 到 5 倍的钱。

AWS Elastic Container Service(ECS)配合 Fargate 就是另一个选择。Fargate 在托管基础设施上运行你的 Docker 容器,不需要运维 EC2 实例,也不用管理集群。你定义想跑什么,AWS 负责"怎么跑"。

问题在于?文档分散在几十个 AWS 页面,大多数教程只到"Hello World"就停了,HTTPS、自定义域名、负载均衡、自动扩缩容这些生产环境真正需要的东西根本不涉及。

这篇指南不一样。我们从零开始部署一个真实的 Web 应用到生产级别,包括其他教程都跳过的每一个步骤。

学完这篇指南,你将拥有:

  • ✅ 一个存在 Amazon ECR 里的 Docker 镜像
  • ✅ 一个 24 小时运行的 ECS Fargate 服务
  • ✅ 配置好 HTTPS 的应用负载均衡器(ALB)
  • ✅ 指向你服务的自定义域名
  • ✅ 能应对流量高峰的自动扩缩容
  • ✅ 用于调试的 CloudWatch 日志
  • ✅ 自动化部署的 CI/CD 流水线

开始搭建。

8 Steps to Deploy on ECS Fargate


准备工作

开始之前,你需要准备这些东西:

要求 如何获取
AWS 账号 注册,免费套餐包含一些 ECS 资源
AWS CLI v2 brew install awscli(Mac)或安装指南
Docker Docker Desktop 或 OrbStack
一个用 Docker 容器化的应用 如果没有,可以参考我们的Web 开发者 Docker 指南
一个域名(可选) 用于第 7 步的 HTTPS 配置

配置 AWS CLI:

aws configure
# AWS Access Key ID: <你的访问密钥>
# AWS Secret Access Key: <你的私有密钥>
# Default region name: us-east-1
# Default output format: json
Enter fullscreen mode Exit fullscreen mode

💡 提示: 生产环境建议用 IAM Identity Center(SSO)而不是长期有效的访问密钥。这个我们会在《IAM 角色详解》文章里详细讲。


整体架构是怎么串联的

开始点点之前,先看看我们要搭建的完整架构:

ECS Fargate Deployment Architecture

请求流程是这样的:

  1. 用户 访问你的域名(比如 app.yourdomain.com
  2. Route 53(DNS 服务)把它解析到你的 ALB
  3. 应用负载均衡器 终止 HTTPS(通过 ACM 证书)并路由流量
  4. ECS 服务 维持期望数量的运行中任务
  5. Fargate 任务 从 ECR 拉取 Docker 镜像并运行容器
  6. CloudWatch 日志 捕获容器标准输出/标准错误用于调试
  7. IAM 角色 授权容器访问 AWS 服务

现在来逐个搭建这些组件。


步骤 1:把 Docker 镜像推送到 ECR

Amazon Elastic Container Registry(ECR)是 AWS 的私有 Docker 镜像仓库,ECS 从这里拉取镜像。

创建 ECR 仓库

aws ecr create-repository \
  --repository-name my-web-app \
  --region us-east-1 \
  --image-scanning-configuration scanOnPush=true \
  --encryption-configuration encryptionType=AES256
Enter fullscreen mode Exit fullscreen mode

scanOnPush=true 开启每次推送时自动扫描漏洞,免费且强烈推荐。

构建、标记和推送

# 1. 获取你的 AWS 账号 ID
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)

# 2. 让 Docker 通过 ECR 认证
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin \
  ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com

# 3. 构建镜像(x86 架构,Fargate 默认使用的)
docker build --platform linux/amd64 -t my-web-app .

# 4. 标记为 ECR 镜像
docker tag my-web-app:latest \
  ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/my-web-app:latest

# 5. 推送
docker push \
  ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/my-web-app:latest
Enter fullscreen mode Exit fullscreen mode

⚠️ 使用苹果芯片的用户(M1/M2/M3):--platform linux/amd64 这个参数很关键。没有它的话,构建的是 ARM 镜像,在 x86 Fargate 上可能会崩溃。也可以用 --platform linux/arm64 然后把 Fargate 任务配置为 ARM(Graviton 处理器),这样便宜 20%。

验证推送结果

aws ecr describe-images \
  --repository-name my-web-app \
  --region us-east-1
Enter fullscreen mode Exit fullscreen mode

应该能看到你的镜像及其摘要和大小。


步骤 2:创建 ECS 集群

ECS 集群是任务和服务的逻辑分组。用 Fargate 的话,集群本质上就是个命名空间——没有 EC2 实例需要管理。

aws ecs create-cluster \
  --cluster-name my-app-cluster \
  --setting name=containerInsights,value=enabled
Enter fullscreen mode Exit fullscreen mode

Container Insights 会把 CPU、内存和网络指标添加到 CloudWatch,生产环境调试时很有用。

就这么简单。一条命令,集群就准备好了。


步骤 3:创建任务执行 IAM 角色

ECS 需要一个 IAM 角色来代替你从 ECR 拉取镜像和发送日志到 CloudWatch。

创建信任策略

cat > ecs-trust-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
Enter fullscreen mode Exit fullscreen mode

创建角色

# 创建角色
aws iam create-role \
  --role-name ecsTaskExecutionRole \
  --assume-role-policy-document file://ecs-trust-policy.json

# 附加托管策略
aws iam attach-role-policy \
  --role-name ecsTaskExecutionRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Enter fullscreen mode Exit fullscreen mode

这授权 ECS 可以:

  • 从 ECR 拉取镜像
  • 创建并写入 CloudWatch 日志组
  • (可选)从 AWS Secrets Manager 或 SSM 参数存储读取密钥

步骤 4:创建任务定义

任务定义是你容器的蓝图。它定义了运行哪个镜像、分配多少 CPU/内存、暴露哪些端口、以及日志发到哪里。

创建任务定义 JSON

cat > task-definition.json << EOF
{
  "family": "my-web-app",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "executionRoleArn": "arn:aws:iam::${AWS_ACCOUNT_ID}:role/ecsTaskExecutionRole",
  "containerDefinitions": [
    {
      "name": "web",
      "image": "${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/my-web-app:latest",
      "portMappings": [
        {
          "containerPort": 3000,
          "hostPort": 3000,
          "protocol": "tcp"
        }
      ],
      "essential": true,
      "environment": [
        {
          "name": "NODE_ENV",
          "value": "production"
        },
        {
          "name": "PORT",
          "value": "3000"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/my-web-app",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs",
          "awslogs-create-group": "true"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1"],
        "interval": 30,
        "timeout": 5,
        "retries": 3,
        "startPeriod": 60
      }
    }
  ]
}
EOF
Enter fullscreen mode Exit fullscreen mode

注册任务定义

aws ecs register-task-definition \
  --cli-input-json file://task-definition.json
Enter fullscreen mode Exit fullscreen mode

配置说明

设置项 原因
cpu: "256" 0.25 vCPU 最小 Fargate 规格;低流量 API 够用
memory: "512" 512 MB 必须和 CPU 兼容(见