Deploying Docker containers on ECS

预计阅读时间:21分钟

Overview

Docker Compose CLI 使开发人员能够在构建云原生应用程序时使用原生 Docker 命令在 Amazon Elastic Container Service (ECS) 中运行应用程序.

Docker 和 Amazon ECS 之间的集成允许开发人员使用 Docker Compose CLI 来:

  • 在一个 Docker 命令中设置 AWS 上下文,允许您从本地上下文切换到云上下文并快速轻松地运行应用程序
  • 使用 Compose 文件简化 Amazon ECS 上的多容器应用程序开发

另请参阅ECS 集成架构撰写功能的完整列表ECS 集成的撰写示例.

Prerequisites

要在 ECS 上部署 Docker 容器,您必须满足以下要求:

  1. 下载并安装最新版本的 Docker Desktop.

    或者,安装适用于 Linux 的 Docker Compose CLI .

  2. 确保您拥有 AWS 账户.

Docker 不仅可以在本地运行多容器应用程序,还可以让开发人员通过docker compose up命令使用 Compose 文件在 Amazon ECS 上无缝部署 Docker 容器. 以下部分包含有关如何在 Amazon ECS 上部署 Compose 应用程序的说明.

Run an application on ECS

Requirements

AWS 使用细粒度的权限模型,每个资源类型和操作都有特定的角色.

为确保允许 Docker ECS 集成为您的 Compose 应用程序管理资源,您必须确保您的 AWS 凭证授予对以下 AWS IAM 权限的访问权限

  • application-autoscaling:*
  • cloudformation:*
  • ec2:AuthorizeSecurityGroupIngress
  • ec2:CreateSecurityGroup
  • ec2:CreateTags
  • ec2:DeleteSecurityGroup
  • ec2:DescribeRouteTables
  • ec2:DescribeSecurityGroups
  • ec2:DescribeSubnets
  • ec2:DescribeVpcs
  • ec2:RevokeSecurityGroupIngress
  • ecs:CreateCluster
  • ecs:CreateService
  • ecs:DeleteCluster
  • ecs:DeleteService
  • ecs:DeregisterTaskDefinition
  • ecs:DescribeClusters
  • ecs:DescribeServices
  • ecs:DescribeTasks
  • ecs:ListAccountSettings
  • ecs:ListTasks
  • ecs:RegisterTaskDefinition
  • ecs:UpdateService
  • elasticloadbalancing:*
  • iam:AttachRolePolicy
  • iam:CreateRole
  • iam:DeleteRole
  • iam:DetachRolePolicy
  • iam:PassRole
  • logs:CreateLogGroup
  • logs:DeleteLogGroup
  • logs:DescribeLogGroups
  • logs:FilterLogEvents
  • route53:CreateHostedZone
  • route53:DeleteHostedZone
  • route53:GetHealthCheck
  • route53:GetHostedZone
  • route53:ListHostedZonesByName
  • servicediscovery:*

GPU 支持依赖于 EC2 实例来运行带有附加 GPU 设备的容器,需要一些额外的权限:

  • ec2:DescribeVpcs
  • autoscaling:*
  • iam:CreateInstanceProfile
  • iam:AddRoleToInstanceProfile
  • iam:RemoveRoleFromInstanceProfile
  • iam:DeleteInstanceProfile

Create AWS context

运行docker context create ecs myecscontext命令以创建名为myecscontext的 Amazon ECS Docker 上下文. 如果您已经安装并配置了 AWS CLI,则 setup 命令允许您选择现有的 AWS 配置文件以连接到 Amazon. 否则,您可以通过传递AWS 访问密钥 ID 和秘密访问密钥来创建新配置文件. 最后,您可以配置 ECS 上下文以通过AWS_*环境变量检索 AWS 凭证,这是与第三方工具和单点登录提供商集成的常用方法.

? Create a Docker context using:  [Use arrows to move, type to filter]
  An existing AWS profile
  AWS secret and token credentials
> AWS environment variables

创建 AWS 上下文后,您可以通过运行docker context ls命令列出您的 Docker 上下文:

NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
myecscontext        ecs                 credentials read from environment
default *           moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                         swarm

Run a Compose application

您可以使用docker compose命令将 Compose 文件中定义的多容器应用程序部署和管理到 Amazon ECS. 去做这个:

  • 确保您使用的是 ECS 上下文. 您可以通过使用命令指定--context myecscontext标志来执行此操作,或者使用命令docker context use myecscontext设置当前上下文.

  • 运行docker compose updocker compose down以启动然后停止完整的 Compose 应用程序.

    默认情况下, compose.yaml docker compose up使用当前文件夹中的 compose.yaml 或docker-compose.yaml文件. 您可以使用 --workdir 标志指定工作目录,也可以直接使用docker compose --file mycomposefile.yaml up指定 Compose 文件.

    您还可以在部署期间使用--project-name标志为 Compose 应用程序指定名称. 如果未指定名称,则名称将从工作目录派生.

Docker ECS 集成将 Compose 应用程序模型转换为一组 AWS 资源,称为CloudFormation模板. 实际映射在技术文档中进行了描述. 您可以使用docker compose convert命令查看生成的模板,并在运行docker compose up时按照 CloudFormation 在AWS Web 控制台中应用此模型,此外还会在终端中显示 CloudFormation 事件.

  • 您可以使用docker compose ps命令查看为 Amazon ECS 上的 Compose 应用程序创建的服务及其状态.

  • 您可以使用docker compose logs命令从属于 Compose 应用程序的容器中查看日志.

另请参阅撰写功能的完整列表.

Rolling update

要在不中断生产流程的情况下更新您的应用程序,您只需在更新的 Compose 项目上使用docker compose up . 您的 ECS 服务是使用滚动更新配置创建的. 当您使用修改后的 Compose 文件运行docker compose up时,堆栈将更新以反映更改,并且如果需要,一些服务将被替换. 此替换过程将遵循您的服务deploy.update_config配置设置的滚动更新配置.

AWS ECS 使用基于百分比的模型来定义滚动更新期间要运行或关闭的容器数量. Docker Compose CLI 根据parallelismreplicas字段计算滚动更新配置. 但是,您可能更喜欢使用扩展字段x-aws-min_percentx-aws-max_percent直接配置滚动更新. 前者设置为服务运行的容器的最小百分比,后者设置在删除以前的版本之前启动的附加容器的最大百分比.

默认情况下,ECS 滚动更新设置为运行一个服务的容器数量的两倍 (200%),并且可以在更新期间关闭 100% 的容器.

View application logs

Docker Compose CLI 为您的容器配置 AWS CloudWatch Logs 服务. 默认情况下,您可以像查看本地部署日志一样查看撰写应用程序的日志:

# fetch logs for application in current working directory
$ docker compose logs

# specify compose project name
$ docker compose --project-name PROJECT logs

# specify compose file
$ docker compose --file /path/to/docker-compose.yaml logs

为应用程序创建一个日志组作为docker-compose/<application_name> ,并为应用程序中的每个服务和容器创建日志流作为<application_name>/<service_name>/<container_ID> .

您可以使用 Compose 文件中的扩展字段x-aws-logs_retention微调 AWS CloudWatch Logs,以设置日志事件的保留天数. 默认行为是永久保留日志.

您还可以将awslogs参数作为标准 Compose 文件logging.driver_opts元素传递给您的容器. 有关可用日志驱动程序选项的详细信息,请参阅AWS 文档.

Private Docker images

Docker Compose CLI 自动配置授权,以便您可以从同一 AWS 账户上的 Amazon ECR 注册表中提取私有映像. 要从另一个注册表(包括 Docker Hub)中提取私有映像,您必须在AWS Secrets Manager 服务上创建一个用户名 + 密码(或一个用户名 + 令牌)密钥.

为方便起见,Docker Compose CLI 提供了docker secret命令,因此您可以管理在 AWS SMS 上创建的密钥,而无需安装 AWS CLI.

首先,创建一个token.json文件来定义您的 DockerHub 用户名和访问令牌.

有关如何生成访问令牌的说明,请参阅管理访问令牌.

{
  "username":"DockerHubUserName",
  "password":"DockerHubAccessToken"
}

然后,您可以使用docker secret从此文件创建一个秘密:

$ docker secret create dockerhubAccessToken token.json
arn:aws:secretsmanager:eu-west-3:12345:secret:DockerHubAccessToken

创建后,您可以在 Compose 文件中使用此 ARN,使用x-aws-pull_credentials自定义扩展和服务的 Docker 映像 URI.

services:
  worker:
    image: mycompany/privateimage
    x-aws-pull_credentials: "arn:aws:secretsmanager:eu-west-3:12345:secret:DockerHubAccessToken"

Note

如果将 Compose 文件版本设置为 3.8 或更高版本,则可以使用相同的 Compose 文件使用docker-compose进行本地部署. 在这种情况下,自定义 ECS 扩展将被忽略.

Service discovery

服务到服务的通信默认是透明实现的,因此您可以使用多个互连的服务部署您的 Compose 应用程序,而无需在本地和 ECS 部署之间更改 compose 文件. 单个服务可以在不同的约束(内存、cpu)和复制规则下运行.

Service names

服务在应用程序部署期间由AWS Cloud Map上的 Docker Compose CLI 自动注册. 它们被声明为以下形式的完全限定域名: <service>.<compose_project_name>.local .

服务可以使用 Compose 服务名称检索它们的依赖项(就像使用 docker-compose 在本地部署时所做的那样),或者可以选择使用完全限定名称.

Note

除非您在 VPC 中启用公共 dns 名称,否则短服务名称或完全限定的服务名称都将解析.

Dependent service startup time and DNS resolution

部署 Compose 文件时,服务会在 ECS 上同时调度. AWS Cloud Map 引入了 DNS 服务能够解析您的服务域名的初始延迟. 您的代码需要通过等待相关服务准备好或通过添加等待脚本作为 Docker 映像的入口点来支持此延迟,如控制启动顺序中所述. 请注意,当使用 docker-compose 在本地部署时,也需要在 Compose 应用程序中等待依赖服务,但延迟通常更短. 如果服务不等待其依赖项可用,则在部署到 ECS 时问题可能会变得更加明显.

或者,您可以使用 Compose 文件格式的depends_on功能. 通过这样做,将首先创建依赖服务,应用程序部署将等待它启动并运行,然后再开始创建依赖服务.

Service isolation

服务隔离由安全组规则实现,允许共享公共 Compose 文件"网络"的服务使用它们的 Compose 服务名称进行通信.

Volumes

ECS 集成支持基于 Amazon Elastic File System (Amazon EFS) 的卷管理. 对于声明volume的 Compose 文件,ECS 集成将定义在 CloudFormation 模板中创建 EFS 文件系统,并使用Retain策略,因此在应用程序关闭时不会删除数据. 如果再次部署相同的应用程序(相同的项目名称),文件系统将被重新附加,以提供开发人员习惯使用 docker-compose 的相同用户体验.

可以像这样声明使用卷的基本撰写服务:

services:
  nginx:
    image: nginx
    volumes:
      - mydata:/some/container/path
volumes:
  mydata:

如果没有特定的卷选项,仍然必须在volumes部分中声明卷以使 compose 文件有效(在上面的示例中为空的mydata:条目)如果需要,可以使用driver-opts自定义初始文件系统:

volumes:
  my-data:
    driver_opts:
      # Filesystem configuration
      backup_policy: ENABLED
      lifecycle_policy: AFTER_14_DAYS
      performance_mode: maxIO
      throughput_mode: provisioned
      provisioned_throughput: 1

通过在 AWS 上执行docker compose up创建的文件系统可以使用docker volume ls并使用docker volume rm <filesystemID>删除.

现有文件系统也可用于已在 EFS 上存储数据或想要使用由另一个 Compose 堆栈创建的文件系统的用户.

volumes:
  my-data:
    external: true
    name: fs-123abcd

从容器访问卷可能会引入 POSIX 用户 ID 权限问题,因为 Docker 映像可以定义任意用户 ID/组 ID,以便进程在容器内运行. 但是,相同的uid:gid必须匹配文件系统上的 POSIX 权限. 要解决可能的冲突,您可以设置访问卷时要使用的卷uidgid

volumes:
  my-data:
    driver_opts:
      # Access point configuration
      uid: 0
      gid: 0

Secrets

您可以使用 Docker 模型将机密传递给您的 ECS 服务,以将敏感数据绑定为/run/secrets下的文件. 如果您的 Compose 文件将机密声明为文件,则此类机密将作为您在 ECS 上的应用程序部署的一部分创建. 如果您在 Compose 文件中使用现有密钥作为external: true引用,请使用 ECS Secrets Manager 完整 ARN 作为密钥名称:

services:
  webapp:
    image: ...
    secrets:
      - foo

secrets:
  foo:
    name: "arn:aws:secretsmanager:eu-west-3:1234:secret:foo-ABC123"
    external: true

秘密将在运行时以纯文本文件/run/secrets/foo的形式提供给您的服务.

AWS Secrets Manager 允许您将敏感数据存储为纯文本(如 Docker 机密)或分层 JSON 文档. 您可以将后者与 Docker Compose CLI 一起使用,方法是使用自定义字段x-aws-keys来定义 JSON 文档中的哪些条目要绑定为服务容器中的机密.

services:
  webapp:
    image: ...
    secrets:
      - foo

secrets:
  foo:
    name: "arn:aws:secretsmanager:eu-west-3:1234:secret:foo-ABC123"
    x-aws-keys:
      - "bar"

通过这样做, bar key 的密钥将在运行时以纯文本文件/run/secrets/foo/bar的形式提供给您的服务. 您可以使用特殊值*来获取容器中绑定的所有键.

Auto scaling

可以使用正常的 Compose 语法指定缩放服务静态信息(非自动缩放):

services:
  foo:
    deploy:
      replicas: 3

Compose 文件模型没有定义任何属性来声明自动缩放条件. 因此,我们依靠x-aws-autoscaling自定义扩展来定义自动缩放范围,以及 cpu内存来定义目标指标,以资源使用百分比表示.

services:
  foo:
    deploy:
      x-aws-autoscaling:
        min: 1
        max: 10 #required
        cpu: 75
        # mem: - mutualy exlusive with cpu

IAM roles

您的 ECS 任务使用专用 IAM 角色执行,授予对 AWS 托管策略AmazonECSTaskExecutionRolePolicyAmazonEC2ContainerRegistryReadOnly的访问权限. 此外,如果您的服务使用密钥,则 IAM 角色会获得额外的权限以从 AWS Secret Manager 读取和解密密钥.

您可以通过在服务定义中使用x-aws-policies为您的服务执行授予额外的托管策略:

services:
  foo:
    x-aws-policies:
      - "arn:aws:iam::aws:policy/AmazonS3FullAccess"

您还可以编写自己的IAM 策略文档来微调要应用于 ECS 服务的 IAM 角色,并在服务定义中使用x-aws-role来传递 yaml 格式的策略文档.

services:
  foo:
    x-aws-role:
      Version: "2012-10-17"
      Statement:
        - Effect: "Allow"
          Action:
            - "some_aws_service"
          Resource:
            - "*"

Tuning the CloudFormation template

Docker Compose CLI 依赖Amazon CloudFormation来管理应用程序部署. 要对创建的资源进行更多控制,您可以使用docker compose convert从您的 Compose 文件生成 CloudFormation 堆栈文件. 这允许您检查它定义的资源,或根据您的需要自定义模板,然后使用 AWS CLI 或 AWS Web 控制台将模板应用到 AWS.

确定 CloudFormation 模板所需的更改后,您可以在 Compose 文件中包含叠加层,这些叠加层将自动应用于compose up . 叠加层是一个 yaml 对象,它使用与 ECS 集成生成的相同 CloudFormation 模板数据结构,但仅包含要更新或添加的属性. 在应用于 AWS 基础设施之前,它将与生成的模板合并.

Adjusting Load Balancer http HealthCheck configuration

虽然 ECS 集群使用容器上的HealthCheck命令来获取服务运行状况,但 Application Load Balancer 定义了自己的基于 URL 的 HealthCheck 机制,以便路由流量. 由于 Compose 模型(还)不提供这样的抽象,因此应用了默认的,它在/期望 HTTP 状态代码200下查询您的服务.

您可以按照AWS CloudFormation 用户指南进行配置参考,使用 cloudformation 覆盖调整此行为:

services:
  webapp:
    image: acme/webapp
    ports:
      - "80:80"

x-aws-cloudformation:
  Resources:
    WebappTCP80TargetGroup:
      Properties:
        HealthCheckPath: /health
        Matcher:
          HttpCode: 200-499

Setting SSL termination by Load Balancer

您可以使用 Application Load Balancer 来处理 HTTPS 服务的 SSL 终止,这样在容器内运行的代码就不必这样做了. 由于 Compose 规范中缺乏等效的抽象,ECS 集成目前不支持这一点. 但是,您可以依靠覆盖在生成的侦听器配置上启用此功能:

services:
  webapp:
    image: acme/webapp
    ports:
      - "80:80"

x-aws-cloudformation:
  Resources:
    WebappTCP80Listener:
      Properties:
        Certificates:
          - CertificateArn: "arn:aws:acm:certificate/123abc"
        Protocol: HTTPS
        Port: 443

Using existing AWS network resources

默认情况下,Docker Compose CLI 为您的 Compose 应用程序创建一个 ECS 集群,在您的 AWS 账户的默认 VPC 上的 Compose 文件中为每个网络创建一个安全组,以及一个用于将流量路由到您的服务的 LoadBalancer.

使用以下基本 compose 文件,Docker Compose CLI 将自动创建这些 ECS 结构,包括负载均衡器,以将流量路由到公开的端口 80.

services:
  nginx:
    image: nginx
    ports:
      - "80:80"

如果您的 AWS 账户无权创建此类资源,或者您想自己管理这些资源,则可以使用以下自定义 Compose 扩展:

  • 在部署 Compose 应用程序时,使用x-aws-cluster作为 Compose 文件中的顶级元素来设置 ECS 集群的 ID. 否则,将为 Compose 项目创建一个集群.

  • 在部署 Compose 应用程序时,使用x-aws-vpc作为 Compose 文件中的顶级元素来设置 VPC 的 ARN.

  • 使用x-aws-loadbalancer作为 Compose 文件中的顶级元素来设置现有 LoadBalancer 的 ARN.

后者可用于那些想要自定义应用程序公开的人,通常是为您的应用程序使用现有域名:

  1. 使用 AWS Web 控制台或 CLI 获取您的 VPC 和子网 ID. 您可以使用以下 AWS CLI 命令检索默认 VPC ID 和附加子网:

     ```console
     $ aws ec2 describe-vpcs --filters Name=isDefault,Values=true --query 'Vpcs[0].VpcId'
        
     "vpc-123456"
     $ aws ec2 describe-subnets --filters Name=vpc-id,Values=vpc-123456 --query 'Subnets[*].SubnetId'
        
     [
         "subnet-1234abcd",
         "subnet-6789ef00",
     ]
     ```
    
  2. 使用 AWS CLI 创建您的负载均衡器. 也可以使用 AWS Web 控制台,但需要添加至少一个侦听器,我们在这里不需要.

     ```console
     $ aws elbv2 create-load-balancer --name myloadbalancer --type application --subnets "subnet-1234abcd" "subnet-6789ef00"
        
     {
         "LoadBalancers": [
             {
                 "IpAddressType": "ipv4",
                 "VpcId": "vpc-123456",
                 "LoadBalancerArn": "arn:aws:elasticloadbalancing:us-east-1:1234567890:loadbalancer/app/myloadbalancer/123abcd456",
                 "DNSName": "myloadbalancer-123456.us-east-1.elb.amazonaws.com",
     <...>
     ```
    
  3. 要为您的应用程序分配现有域名,您可以使用 CNAME 条目配置您的 DNS,该条目指向刚刚创建的负载均衡器的DNSName ,该名称在您创建负载均衡器时报告.

  4. 使用 Loadbalancer ARN 在您的 compose 文件中设置x-aws-loadbalancer ,并使用docker compose up命令部署您的应用程序.

Please note Docker ECS integration won’t be aware of this domain name, so docker compose ps command will report URLs with loadbalancer DNSName, not your own domain.

您还可以在 Compose 文件中的网络定义中使用external: true ,以便 Docker Compose CLI创建安全组,并将name设置为要用于服务之间网络连接的现有安全组的 ID:

networks:
  back_tier:
    external: true
    name: "sg-1234acbd"

Local simulation

当您在 ECS 上部署应用程序时,您还可能依赖其他 AWS 服务. 在这种情况下,您的代码必须嵌入 AWS 开发工具包并在运行时检索 API 凭证. AWS 提供了一种完全由 SDK 实现的凭证发现机制,并依赖于访问固定 IP 地址上的元数据服务.

一旦采用这种方法,在本地运行应用程序以进行测试或调试可能会很困难. 因此,我们引入了上下文创建选项来设置ecs-local上下文,以维护本地工作站和 AWS 云提供商之间的应用程序可移植性.

$ docker context create ecs --local-simulation ecsLocal
Successfully created ecs-local context "ecsLocal"

当您选择本地模拟上下文时,运行docker compose up命令不会在 ECS 上部署您的应用程序. 因此,您必须在本地运行它,自动调整您的 Compose 应用程序,使其包含ECS 本地端点. 这允许应用程序代码使用的 AWS 开发工具包以"AWS 元数据 API"的形式访问本地模拟容器,并从您自己的本地.aws/credentials配置文件中检索凭证.

Install the Docker Compose CLI on Linux

Docker Compose CLI 添加了对在 ECS 上运行和管理容器的支持.

Install Prerequisites

Docker 19.03 或更高版本

Install script

您可以使用安装脚本安装新的 CLI:

$ curl -L https://raw.githubusercontent.com/docker/compose-cli/main/scripts/install/install_linux.sh | sh

FAQ

this tool requires the "new ARN resource ID format"的错误是什么意思?

此错误消息表示您的账户需要 ECS 的新 ARN 资源 ID 格式. 要了解更多信息,请参阅将您的 Amazon ECS 部署迁移到新的 ARN 和资源 ID 格式.

Feedback

感谢您试用 Docker Compose CLI. 您的反馈对我们来说很重要. 通过在Compose CLI GitHub 存储库中创建问题,让我们知道您的反馈.

Docker, AWS, ECS, Integration, context, Compose, cli, deploy, containers, cloud

by  icopy.site