1+ AWSTemplateFormatVersion : ' 2010-09-09'
2+ Description : ' Spotify Data Explorer - Infrastructure as Code'
3+
4+ Parameters :
5+ ECRRepositoryName :
6+ Type : String
7+ Default : spotify-data-explorer
8+ Description : Name of the ECR repository to store Docker images
9+
10+ AppName :
11+ Type : String
12+ Default : spotify-data-explorer
13+ Description : Name of the application
14+
15+ ContainerPort :
16+ Type : Number
17+ Default : 5000
18+ Description : Port that the container exposes
19+
20+ EnvironmentName :
21+ Type : String
22+ Default : prod
23+ AllowedValues :
24+ - dev
25+ - staging
26+ - prod
27+ Description : Environment name
28+
29+ Resources :
30+ # ECR Repository
31+ ECRRepository :
32+ Type : AWS::ECR::Repository
33+ Properties :
34+ RepositoryName : !Ref ECRRepositoryName
35+ RepositoryPolicyText :
36+ Version : ' 2012-10-17'
37+ Statement :
38+ - Sid : AllowPull
39+ Effect : Allow
40+ Principal :
41+ Service :
42+ - ecs.amazonaws.com
43+ - ecs-tasks.amazonaws.com
44+ Action :
45+ - ecr:GetDownloadUrlForLayer
46+ - ecr:BatchGetImage
47+ - ecr:BatchCheckLayerAvailability
48+
49+ # VPC for ECS Fargate
50+ VPC :
51+ Type : AWS::EC2::VPC
52+ Properties :
53+ CidrBlock : 10.0.0.0/16
54+ EnableDnsSupport : true
55+ EnableDnsHostnames : true
56+ Tags :
57+ - Key : Name
58+ Value : !Sub ${AppName}-vpc
59+
60+ # Internet Gateway
61+ InternetGateway :
62+ Type : AWS::EC2::InternetGateway
63+ Properties :
64+ Tags :
65+ - Key : Name
66+ Value : !Sub ${AppName}-igw
67+
68+ # Attach Internet Gateway to VPC
69+ InternetGatewayAttachment :
70+ Type : AWS::EC2::VPCGatewayAttachment
71+ Properties :
72+ InternetGatewayId : !Ref InternetGateway
73+ VpcId : !Ref VPC
74+
75+ # Public Subnet 1
76+ PublicSubnet1 :
77+ Type : AWS::EC2::Subnet
78+ Properties :
79+ VpcId : !Ref VPC
80+ AvailabilityZone : !Select [ 0, !GetAZs '' ]
81+ CidrBlock : 10.0.1.0/24
82+ MapPublicIpOnLaunch : true
83+ Tags :
84+ - Key : Name
85+ Value : !Sub ${AppName}-public-subnet-1
86+
87+ # Public Subnet 2
88+ PublicSubnet2 :
89+ Type : AWS::EC2::Subnet
90+ Properties :
91+ VpcId : !Ref VPC
92+ AvailabilityZone : !Select [ 1, !GetAZs '' ]
93+ CidrBlock : 10.0.2.0/24
94+ MapPublicIpOnLaunch : true
95+ Tags :
96+ - Key : Name
97+ Value : !Sub ${AppName}-public-subnet-2
98+
99+ # Public Route Table
100+ PublicRouteTable :
101+ Type : AWS::EC2::RouteTable
102+ Properties :
103+ VpcId : !Ref VPC
104+ Tags :
105+ - Key : Name
106+ Value : !Sub ${AppName}-public-route-table
107+
108+ # Public Route
109+ PublicRoute :
110+ Type : AWS::EC2::Route
111+ DependsOn : InternetGatewayAttachment
112+ Properties :
113+ RouteTableId : !Ref PublicRouteTable
114+ DestinationCidrBlock : 0.0.0.0/0
115+ GatewayId : !Ref InternetGateway
116+
117+ # Public Subnet 1 Route Table Association
118+ PublicSubnet1RouteTableAssociation :
119+ Type : AWS::EC2::SubnetRouteTableAssociation
120+ Properties :
121+ RouteTableId : !Ref PublicRouteTable
122+ SubnetId : !Ref PublicSubnet1
123+
124+ # Public Subnet 2 Route Table Association
125+ PublicSubnet2RouteTableAssociation :
126+ Type : AWS::EC2::SubnetRouteTableAssociation
127+ Properties :
128+ RouteTableId : !Ref PublicRouteTable
129+ SubnetId : !Ref PublicSubnet2
130+
131+ # ECS Cluster
132+ ECSCluster :
133+ Type : AWS::ECS::Cluster
134+ Properties :
135+ ClusterName : !Sub ${AppName}-cluster
136+ CapacityProviders :
137+ - FARGATE
138+ DefaultCapacityProviderStrategy :
139+ - CapacityProvider : FARGATE
140+ Weight : 1
141+
142+ # ECS Task Execution Role
143+ ECSTaskExecutionRole :
144+ Type : AWS::IAM::Role
145+ Properties :
146+ AssumeRolePolicyDocument :
147+ Version : ' 2012-10-17'
148+ Statement :
149+ - Effect : Allow
150+ Principal :
151+ Service : ecs-tasks.amazonaws.com
152+ Action : sts:AssumeRole
153+ ManagedPolicyArns :
154+ - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
155+
156+ # ECS Task Definition
157+ ECSTaskDefinition :
158+ Type : AWS::ECS::TaskDefinition
159+ Properties :
160+ Family : !Sub ${AppName}-task
161+ Cpu : ' 256'
162+ Memory : ' 512'
163+ NetworkMode : awsvpc
164+ RequiresCompatibilities :
165+ - FARGATE
166+ ExecutionRoleArn : !GetAtt ECSTaskExecutionRole.Arn
167+ ContainerDefinitions :
168+ - Name : !Ref AppName
169+ Image : !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepositoryName}:latest
170+ Essential : true
171+ PortMappings :
172+ - ContainerPort : !Ref ContainerPort
173+ HostPort : !Ref ContainerPort
174+ Protocol : tcp
175+ LogConfiguration :
176+ LogDriver : awslogs
177+ Options :
178+ awslogs-group : !Ref LogGroup
179+ awslogs-region : !Ref AWS::Region
180+ awslogs-stream-prefix : ecs
181+
182+ # Log Group for Container Logs
183+ LogGroup :
184+ Type : AWS::Logs::LogGroup
185+ Properties :
186+ LogGroupName : !Sub /ecs/${AppName}
187+ RetentionInDays : 30
188+
189+ # Security Group for ECS Service
190+ ServiceSecurityGroup :
191+ Type : AWS::EC2::SecurityGroup
192+ Properties :
193+ GroupDescription : Security group for Spotify Data Explorer service
194+ VpcId : !Ref VPC
195+ SecurityGroupIngress :
196+ - IpProtocol : tcp
197+ FromPort : !Ref ContainerPort
198+ ToPort : !Ref ContainerPort
199+ CidrIp : 0.0.0.0/0
200+
201+ # ALB Security Group
202+ ALBSecurityGroup :
203+ Type : AWS::EC2::SecurityGroup
204+ Properties :
205+ GroupDescription : Security group for the Application Load Balancer
206+ VpcId : !Ref VPC
207+ SecurityGroupIngress :
208+ - IpProtocol : tcp
209+ FromPort : 80
210+ ToPort : 80
211+ CidrIp : 0.0.0.0/0
212+ - IpProtocol : tcp
213+ FromPort : 443
214+ ToPort : 443
215+ CidrIp : 0.0.0.0/0
216+
217+ # Application Load Balancer
218+ ApplicationLoadBalancer :
219+ Type : AWS::ElasticLoadBalancingV2::LoadBalancer
220+ Properties :
221+ Name : !Sub ${AppName}-alb
222+ Scheme : internet-facing
223+ LoadBalancerAttributes :
224+ - Key : idle_timeout.timeout_seconds
225+ Value : ' 60'
226+ Subnets :
227+ - !Ref PublicSubnet1
228+ - !Ref PublicSubnet2
229+ SecurityGroups :
230+ - !Ref ALBSecurityGroup
231+ Tags :
232+ - Key : Name
233+ Value : !Sub ${AppName}-alb
234+
235+ # ALB Target Group
236+ ALBTargetGroup :
237+ Type : AWS::ElasticLoadBalancingV2::TargetGroup
238+ Properties :
239+ Name : !Sub ${AppName}-tg
240+ Port : !Ref ContainerPort
241+ Protocol : HTTP
242+ TargetType : ip
243+ VpcId : !Ref VPC
244+ HealthCheckPath : /
245+ HealthCheckIntervalSeconds : 30
246+ HealthCheckTimeoutSeconds : 5
247+ HealthyThresholdCount : 3
248+ UnhealthyThresholdCount : 3
249+ TargetGroupAttributes :
250+ - Key : deregistration_delay.timeout_seconds
251+ Value : ' 30'
252+
253+ # ALB Listener
254+ ALBListener :
255+ Type : AWS::ElasticLoadBalancingV2::Listener
256+ Properties :
257+ DefaultActions :
258+ - Type : forward
259+ TargetGroupArn : !Ref ALBTargetGroup
260+ LoadBalancerArn : !Ref ApplicationLoadBalancer
261+ Port : 80
262+ Protocol : HTTP
263+
264+ # ECS Service
265+ ECSService :
266+ Type : AWS::ECS::Service
267+ DependsOn : ALBListener
268+ Properties :
269+ ServiceName : !Sub ${AppName}-service
270+ Cluster : !Ref ECSCluster
271+ TaskDefinition : !Ref ECSTaskDefinition
272+ DesiredCount : 1
273+ LaunchType : FARGATE
274+ NetworkConfiguration :
275+ AwsvpcConfiguration :
276+ AssignPublicIp : ENABLED
277+ SecurityGroups :
278+ - !Ref ServiceSecurityGroup
279+ Subnets :
280+ - !Ref PublicSubnet1
281+ - !Ref PublicSubnet2
282+ LoadBalancers :
283+ - ContainerName : !Ref AppName
284+ ContainerPort : !Ref ContainerPort
285+ TargetGroupArn : !Ref ALBTargetGroup
286+
287+ Outputs :
288+ ECRRepositoryURL :
289+ Description : URL of the ECR Repository
290+ Value : !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepositoryName}
291+
292+ ServiceURL :
293+ Description : URL of the deployed service
294+ Value : !Sub http://${ApplicationLoadBalancer.DNSName}
295+
296+ ECSClusterName :
297+ Description : Name of the ECS Cluster
298+ Value : !Ref ECSCluster
299+
300+ ECSServiceName :
301+ Description : Name of the ECS Service
302+ Value : !Ref ECSService
0 commit comments