在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上,必须满足以下要求:
-
下载并安装最新版本的Docker Desktop。
或者,安装适用于Linux的Docker Compose CLI。
-
确保您拥有一个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 up
并docker compose down
启动,然后停止完整的Compose应用程序。默认情况下,
docker compose up
使用当前文件夹中的compose.yaml
或docker-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根据parallelism
和replicas
字段计算滚动更新配置。但是,您可能更愿意使用扩展字段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权限。要解决可能的冲突,可以设置卷
uid
并gid
在访问卷时使用它:
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。
后者可用于那些想要自定义应用程序公开程度的人,通常是将现有域名用于您的应用程序:
- 使用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",
]
- 使用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",
...
-
要为您的应用程序分配现有域名,您可以使用CNAME条目配置DNS,该条目指向刚创建的负载均衡器在创建负载均衡器时所
DNSName
报告的内容。 -
使用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上运行和管理容器的支持。
安装先决条件
安装脚本
您可以使用安装脚本来安装新的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存储库中创建问题,让我们知道您的反馈。
Docker,AWS,ECS,集成,上下文,编写,cli,部署,容器,云