在ECS上部署Docker容器

预计阅读时间:21分钟

概述

Docker Compose CLI使开发人员可以在构建云原生应用程序时使用本机Docker命令在Amazon EC2容器服务(ECS)中运行应用程序。

Docker和Amazon ECS之间的集成使开发人员可以使用Docker Compose CLI进行以下操作:

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

另请参阅ECS集成体系结构撰写功能的完整列表ECS集成的撰写示例

先决条件

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

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

    或者,安装适用于LinuxDocker Compose CLI

  2. 确保您拥有一个AWS账户。

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

在ECS上运行应用程序

要求

AWS使用细粒度的权限模型,每种资源类型和操作均具有特定角色。

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

  • 应用程序自动缩放:*
  • 云形成:*
  • ec2:AuthorizeSecurityGroupIngress
  • ec2:CreateSecurityGroup
  • ec2:CreateTags
  • ec2:DeleteSecurityGroup
  • ec2:DescribeRouteTables
  • ec2:DescribeSecurityGroups
  • ec2:描述子网
  • 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
  • 弹性负载平衡:*
  • iam:AttachRolePolicy
  • iam:CreateRole
  • iam:DeleteRole
  • iam:DetachRolePolicy
  • iam:PassRole
  • 日志:CreateLogGroup
  • 日志:DeleteLogGroup
  • 日志:描述日志组
  • 日志:FilterLogEvents
  • route53:CreateHostedZone
  • route53:DeleteHostedZone
  • route53:获取健康检查
  • route53:GetHostedZone
  • route53:ListHostedZonesByName
  • 服务发现:*

GPU支持依赖EC2实例来运行带有连接的GPU设备的容器,还需要一些其他权限:

  • ec2:DescribeVpcs
  • 自动缩放:*
  • iam:CreateInstanceProfile
  • iam:AddRoleToInstanceProfile
  • iam:RemoveRoleFromInstanceProfile
  • iam:DeleteInstanceProfile

创建AWS上下文

运行docker context create ecs myecscontext命令以创建名为的Amazon ECS Docker上下文myecscontext。如果您已经安装并配置了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

运行撰写应用程序

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

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

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

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

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

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

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

  • 您可以使用以下docker compose logs命令查看属于Compose应用程序一部分的容器中的日志。

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

滚动更新

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

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

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

查看应用程序日志

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>

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

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

私人Docker映像

Docker Compose CLI自动配置授权,因此您可以从同一AWS账户上的Amazon ECR注册表提取私有映像。要从包括Docker Hub在内的另一个注册表中提取私有映像,您必须在AWS Secrets Manager服务上创建一个Username + Password(或Username + Token)密钥。

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

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

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

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

然后,您可以使用docker secret以下命令从此文件创建机密:

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

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

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

笔记

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

服务发现

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

服务名称

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

服务可以使用Compose服务名称来检索其依赖关系(与使用docker-compose在本地进行部署时一样),也可以选择使用完全限定的名称。

相关服务启动时间和DNS解析

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

或者,您可以使用Compose文件格式的depends_on功能。这样,将首先创建依赖服务,并且在开始创建依赖服务之前,应用程序部署将等待其启动并运行。

服务隔离

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

卷数

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

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

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

如果没有特定的卷选项,则仍必须在该volumes部分中声明该卷以使撰写文件有效(在上面的示例中为空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

docker compose up可以使用列出docker volume ls和删除通过在AWS上 执行而创建的文件系统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

机密

您可以使用Docker模型将机密传递到ECS服务,以将敏感数据作为文件绑定到/run/secrets。如果您的Compose文件将机密声明为文件,则将在您在ECS上的应用程序部署中创建此机密。如果您external: true在Compose文件中使用现有机密作为参考,请使用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 secret一样)或分层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"
    keys:
      - "bar"

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

自动缩放

扩展服务静态信息(非自动扩展)可以使用常规的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角色

您的ECS任务将以专门的IAM角色执行,从而授予对AWS托管策略AmazonECSTaskExecutionRolePolicy 和的访问权限AmazonEC2ContainerRegistryReadOnly。此外,如果您的服务使用机密,则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:
            - "*"

调整CloudFormation模板

Docker Compose CLI依靠Amazon CloudFormation来管理应用程序部署。要获得对所创建资源的更多控制权,您可以使用docker compose convert从Compose文件生成CloudFormation堆栈文件。这使您可以检查其定义的资源,或根据需要自定义模板,然后使用AWS CLI或AWS Web控制台将模板应用于AWS。

一旦确定了CloudFormation模板所需的更改,便可以在Compose文件中包含叠加层,该叠加层将自动应用于compose up。一个覆盖是使用相同的CloudFormation模板的数据结构通过ECS的集成产生的一个YAML对象,但只包含属性要被更新或添加。在将其应用于AWS基础架构之前,它将与生成的模板合并。

调整负载均衡器http HealthCheck配置

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

通过负载均衡器设置SSL终止

您可以使用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

使用现有的AWS网络资源

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

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

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

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

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

  • 使用x-aws-vpc作为顶级元素在撰写文件部署撰写应用程序时设置的VPC的ARN。

  • 使用x-aws-loadbalancer作为顶级元素在撰写文件设置一个现有的负载平衡器的ARN。

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

  1. 使用AWS Web控制台或CLI获取您的VPC和子网ID。您可以使用以下AWS CLI命令检索默认的VPC ID和附加的子网:
$ 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",
]
  1. 使用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",
...
  1. 要为您的应用程序分配现有域名,您可以使用CNAME条目配置DNS,该条目指向刚创建的负载均衡器在创建负载均衡器时所DNSName报告的内容。

  2. 使用Loadbalancer ARN设置x-aws-loadbalancer您的撰写文件,并使用docker compose up命令部署您的应用程序。

请注意,Docker ECS集成不会知道此域名,因此docker compose ps命令将报告带有负载均衡器DNSName的URL,而不是您自己的域。

您还可以使用external: true在泊坞撰写CLI您撰写的文件网络定义里面没有创建一个安全组,并设置name与您要使用的服务之间的网络连接现有SecurityGroup的ID:

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

本地模拟

在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配置文件中检索凭证。

在Linux上安装Docker Compose CLI

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

安装先决条件

Docker 19.03或更高版本

安装脚本

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

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

常问问题

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

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

反馈

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

DockerAWSECS集成上下文编写cli部署容器