AWSTemplateFormatVersion: '2010-09-09' Description: Deploy a service on AWS Fargate, hosted in a public subnet, and accessible via a public load balancer. Parameters: StackName: Type: String Default: production Description: The name of the parent Fargate networking stack that you created. Necessary to locate and reference resources created by that stack. ServiceName: Type: String Default: nginx Description: A name for the service ImageUrl: Type: String Default: nginx Description: The url of a docker image that contains the application process that will handle the traffic for this service ContainerPort: Type: Number Default: 80 Description: What port number the application inside the docker container is binding to ContainerCpu: Type: Number Default: 256 Description: How much CPU to give the container. 1024 is 1 CPU ContainerMemory: Type: Number Default: 512 Description: How much memory in megabytes to give the container Path: Type: String Default: "*" Description: A path on the public load balancer that this service should be connected to. Use * to send all load balancer traffic to this service. Priority: Type: Number Default: 1 Description: The priority for the routing rule added to the load balancer. This only applies if your have multiple services which have been assigned to different paths on the load balancer. DesiredCount: Type: Number Default: 2 Description: How many copies of the service task to run Role: Type: String Default: "" Description: (Optional) An IAM role to give the service's containers if the code within needs to access other AWS resources like S3 buckets, DynamoDB tables, etc Conditions: HasCustomRole: !Not [ !Equals [!Ref 'Role', ''] ] Resources: # The task definition. This is a simple metadata description of what # container to run, and what resource requirements it has. TaskDefinition: Type: AWS::ECS::TaskDefinition Properties: Family: !Ref 'ServiceName' Cpu: !Ref 'ContainerCpu' Memory: !Ref 'ContainerMemory' NetworkMode: awsvpc RequiresCompatibilities: - FARGATE ExecutionRoleArn: Fn::ImportValue: !Join [':', [!Ref 'StackName', 'ECSTaskExecutionRole']] TaskRoleArn: Fn::If: - 'HasCustomRole' - !Ref 'Role' - !Ref "AWS::NoValue" ContainerDefinitions: - Name: !Ref 'ServiceName' Image: !Ref 'ImageUrl' Essential: true PortMappings: - ContainerPort: !Ref 'ContainerPort' Environment: - Name: VERSION_INFO Value: 'v0' - Name: BUILD_DATE Value: '-' # The service. The service is a resource which allows you to run multiple # copies of a type of task, and gather up their logs and metrics, as well # as monitor the number of running tasks and replace any that have crashed Service: Type: AWS::ECS::Service DependsOn: LoadBalancerRule Properties: ServiceName: !Ref 'ServiceName' Cluster: Fn::ImportValue: !Join [':', [!Ref 'StackName', 'ClusterName']] LaunchType: FARGATE DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 75 DesiredCount: !Ref 'DesiredCount' NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: ENABLED SecurityGroups: - Fn::ImportValue: !Join [':', [!Ref 'StackName', 'FargateContainerSecurityGroup']] Subnets: - Fn::ImportValue: !Join [':', [!Ref 'StackName', 'PublicSubnetOne']] - Fn::ImportValue: !Join [':', [!Ref 'StackName', 'PublicSubnetTwo']] TaskDefinition: !Ref 'TaskDefinition' LoadBalancers: - ContainerName: !Ref 'ServiceName' ContainerPort: !Ref 'ContainerPort' TargetGroupArn: !Ref 'TargetGroup' # A target group. This is used for keeping track of all the tasks, and # what IP addresses / port numbers they have. You can query it yourself, # to use the addresses yourself, but most often this target group is just # connected to an application load balancer, or network load balancer, so # it can automatically distribute traffic across all the targets. TargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 6 HealthCheckPath: / HealthCheckProtocol: HTTP HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 2 TargetType: ip TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: '20' Name: !Ref 'ServiceName' Port: !Ref 'ContainerPort' Protocol: HTTP UnhealthyThresholdCount: 2 VpcId: Fn::ImportValue: !Join [':', [!Ref 'StackName', 'VPCId']] # Create a rule on the load balancer for routing traffic to the target group LoadBalancerRule: Type: AWS::ElasticLoadBalancingV2::ListenerRule Properties: Actions: - TargetGroupArn: !Ref 'TargetGroup' Type: 'forward' Conditions: - Field: path-pattern Values: [!Ref 'Path'] ListenerArn: Fn::ImportValue: !Join [':', [!Ref 'StackName', 'PublicListener']] Priority: !Ref 'Priority'