Skip to content

Commit 044fc7f

Browse files
author
nikhilleo10
committed
feat: deploy application on ecs
1 parent 31379a7 commit 044fc7f

File tree

9 files changed

+441
-9
lines changed

9 files changed

+441
-9
lines changed

README.md

+61-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Initialize local environment
1+
<!-- ## Initialize local environment
22
```
33
./scripts/initialize-env.sh
44
```
@@ -16,4 +16,63 @@ alembic revision -m 'initialize all models'
1616
## Upgrade migrations
1717
```
1818
alembic upgrade head
19-
```
19+
```
20+
21+
## Deploy service on AWS ECS
22+
```
23+
./scripts/setup-ecs.sh develop
24+
```
25+
The `setup-ecs.sh` script deploys the fastapi application on AWS ECS, this script internally uses AWS Copilot to deploy the service. The script requires one argument to successfully deploy the service, the argument that we pass is the environment name, the script creates and deploys an environment and deploys the service on that environment. -->
26+
27+
# FastAPI Template
28+
29+
This repository provides a template for creating and deploying a FastAPI project. Follow the steps below to set up the local environment, run the project, manage database migrations, and deploy the service on AWS ECS.
30+
31+
## Getting Started
32+
33+
### 1. Initialize Local Environment
34+
35+
To set up your local environment, run the following script:
36+
37+
```
38+
./scripts/initialize-env.sh
39+
```
40+
41+
This script installs the necessary dependencies and prepares the environment for running the FastAPI application on your local machine.
42+
43+
### 2. Run the Project
44+
Start the project locally with the following command:
45+
46+
```
47+
./scripts/local_server.sh
48+
```
49+
50+
This script upgrades the database migrations using Alembic and starts the FastAPI server using Uvicorn. The server is hosted on 0.0.0.0 and port 8000, making it accessible locally.
51+
52+
### 3. Database Migrations
53+
Create new database migrations when you make changes to your models. Use the following command:
54+
```
55+
alembic revision -m 'brief description of changes'
56+
```
57+
58+
This command initializes a new migration script based on the changes made to your models. Provide a brief description of the changes in the migration message.
59+
60+
Apply the database migrations with the following command:
61+
```
62+
alembic upgrade head
63+
```
64+
This command updates the database schema to reflect the latest changes defined in the migration scripts
65+
66+
### 4. Deploy Service on AWS ECS
67+
To deploy the FastAPI application on AWS ECS, use the following script:
68+
69+
```
70+
./scripts/setup-ecs.sh develop
71+
```
72+
The setup-ecs.sh script leverages AWS Copilot to deploy the service. Provide the environment name as an argument (e.g., develop). The script creates and deploys an environment, then deploys the FastAPI service on that environment.
73+
74+
Note: Ensure you have AWS credentials configured and AWS Copilot installed for successful deployment.
75+
76+
#### New to AWS Copilot?
77+
If you are new to AWS Copilot or you want to learn more about AWS Copilot, please refer to [this helpful article](https://www.wednesday.is/writing-tutorials/how-to-use-copilot-to-deploy-projects-on-ecs) that guides you through the process of setting up AWS Copilot locally as well as also helps you understand how you can publish and update an application using 4 simple steps.
78+

alembic/env.py

+18-6
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,24 @@
1212

1313
print("==" * 50, "\n\n\n", "OS ENVIRONMENT", os.environ, "\n\n\n", "==" * 50)
1414

15-
print("Connecting local server..\n")
16-
HOST = os.environ["DB_HOSTNAME"]
17-
PORT = os.environ["DB_PORT"]
18-
DBNAME = os.environ["DB_NAME"]
19-
USERNAME = os.environ["DB_USERNAME"]
20-
PASSWORD = os.environ["DB_PASSWORD"]
15+
if "PYTHON_FASTAPI_TEMPLATE_CLUSTER_SECRET" in os.environ:
16+
print("Connecting to database on RDS..\n")
17+
dbSecretJSON = os.environ["PYTHON_FASTAPI_TEMPLATE_CLUSTER_SECRET"]
18+
dbSecretParsed = json.loads(dbSecretJSON)
19+
20+
HOST = dbSecretParsed["host"]
21+
PORT = dbSecretParsed["port"]
22+
DBNAME = dbSecretParsed["dbname"]
23+
USERNAME = dbSecretParsed["username"]
24+
PASSWORD = dbSecretParsed["password"]
25+
26+
else:
27+
print("Connecting local database..\n")
28+
HOST = os.environ["DB_HOSTNAME"]
29+
PORT = os.environ["DB_PORT"]
30+
DBNAME = os.environ["DB_NAME"]
31+
USERNAME = os.environ["DB_USERNAME"]
32+
PASSWORD = os.environ["DB_PASSWORD"]
2133

2234
# this is the Alembic Config object, which provides
2335
# access to the values within the .ini file in use.

config/db.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import os
23
import sys
34

@@ -27,8 +28,21 @@
2728
poolclass=StaticPool,
2829
)
2930

31+
elif "PYTHON_FASTAPI_TEMPLATE_CLUSTER_SECRET" in os.environ:
32+
print("Connecting to database on RDS..\n")
33+
dbSecretJSON = os.environ["PYTHON_FASTAPI_TEMPLATE_CLUSTER_SECRET"]
34+
dbSecretParsed = json.loads(dbSecretJSON)
35+
36+
HOST = dbSecretParsed["host"]
37+
PORT = dbSecretParsed["port"]
38+
DBNAME = dbSecretParsed["dbname"]
39+
USERNAME = dbSecretParsed["username"]
40+
PASSWORD = dbSecretParsed["password"]
41+
42+
engine = create_engine(f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOST}/{DBNAME}")
43+
3044
else:
31-
print("Connecting local server..\n")
45+
print("Connecting local database..\n")
3246
HOST = os.environ["DB_HOSTNAME"]
3347
PORT = os.environ["DB_PORT"]
3448
DBNAME = os.environ["DB_NAME"]

copilot/.workspace

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
application: python-fastapi-template
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
Parameters:
2+
App:
3+
Type: String
4+
Description: Your application's name.
5+
Env:
6+
Type: String
7+
Description: The environment name your service, job, or workflow is being deployed to.
8+
Name:
9+
Type: String
10+
Description: The name of the service, job, or workflow being deployed.
11+
Default: python_fastapi_template
12+
# Customize your Aurora Serverless cluster by setting the default value of the following parameters.
13+
pythonFastApiTemplateclusterDBName:
14+
Type: String
15+
Description: The name of the initial database to be created in the DB cluster.
16+
Default: python_fastapi_template_db
17+
# Cannot have special characters
18+
# Naming constraints: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Limits.html#RDS_Limits.Constraints
19+
pythonFastApiTemplateclusterDBAutoPauseSeconds:
20+
Type: Number
21+
Description: The duration in seconds before the cluster pauses.
22+
Default: 1000
23+
Mappings:
24+
pythonFastApiTemplateclusterEnvScalingConfigurationMap:
25+
prod:
26+
"DBMinCapacity": 1 # AllowedValues: [1, 2, 4, 8, 16, 32, 64, 128, 256]
27+
"DBMaxCapacity": 8 # AllowedValues: [1, 2, 4, 8, 16, 32, 64, 128, 256]
28+
All:
29+
"DBMinCapacity": 1 # AllowedValues: [1, 2, 4, 8, 16, 32, 64, 128, 256]
30+
"DBMaxCapacity": 8 # AllowedValues: [1, 2, 4, 8, 16, 32, 64, 128, 256]
31+
32+
Resources:
33+
pythonFastApiTemplateclusterDBSubnetGroup:
34+
Type: 'AWS::RDS::DBSubnetGroup'
35+
Properties:
36+
DBSubnetGroupDescription: Group of Copilot private subnets for Aurora cluster.
37+
SubnetIds:
38+
!Split [',', { 'Fn::ImportValue': !Sub '${App}-${Env}-PrivateSubnets' }]
39+
pythonFastApiTemplateclusterSecurityGroup:
40+
Metadata:
41+
'aws:copilot:description': 'A security group for your workload to access the DB cluster pythonFastApiTemplatecluster'
42+
Type: 'AWS::EC2::SecurityGroup'
43+
Properties:
44+
GroupDescription: !Sub 'The Security Group for ${Name} to access DB cluster pythonFastApiTemplatecluster.'
45+
VpcId:
46+
Fn::ImportValue:
47+
!Sub '${App}-${Env}-VpcId'
48+
Tags:
49+
- Key: Name
50+
Value: !Sub 'copilot-${App}-${Env}-${Name}-Aurora'
51+
pythonFastApiTemplateclusterDBClusterSecurityGroup:
52+
Metadata:
53+
'aws:copilot:description': 'A security group for your DB cluster pythonFastApiTemplatecluster'
54+
Type: AWS::EC2::SecurityGroup
55+
Properties:
56+
GroupDescription: The Security Group for the database cluster.
57+
SecurityGroupIngress:
58+
- ToPort: 3306
59+
FromPort: 3306
60+
IpProtocol: tcp
61+
SourceSecurityGroupId:
62+
Fn::ImportValue:
63+
!Sub '${App}-${Env}-EnvironmentSecurityGroup'
64+
Description: Allow incoming connections from any IP address.
65+
VpcId:
66+
Fn::ImportValue:
67+
!Sub '${App}-${Env}-VpcId'
68+
Tags:
69+
- Key: Name
70+
Value: !Sub 'copilot-${App}-${Env}-${Name}-Aurora'
71+
pythonFastApiTemplateclusterAuroraSecret:
72+
Metadata:
73+
'aws:copilot:description': 'A Secrets Manager secret to store your DB credentials'
74+
Type: AWS::SecretsManager::Secret
75+
Properties:
76+
Description: !Sub Aurora main user secret for ${AWS::StackName}
77+
GenerateSecretString:
78+
SecretStringTemplate: '{"username": "admin"}'
79+
GenerateStringKey: "password"
80+
ExcludePunctuation: true
81+
IncludeSpace: false
82+
PasswordLength: 16
83+
pythonFastApiTemplateclusterDBClusterParameterGroup:
84+
Metadata:
85+
'aws:copilot:description': 'A DB parameter group for engine configuration values'
86+
Type: 'AWS::RDS::DBClusterParameterGroup'
87+
Properties:
88+
Description: !Ref 'AWS::StackName'
89+
Family: 'aurora-mysql5.7'
90+
Parameters:
91+
character_set_client: 'utf8'
92+
pythonFastApiTemplateclusterDBCluster:
93+
Metadata:
94+
'aws:copilot:description': 'The pythonFastApiTemplatecluster Aurora Serverless database cluster'
95+
Type: 'AWS::RDS::DBCluster'
96+
Properties:
97+
MasterUsername:
98+
!Join [ "", [ '{{resolve:secretsmanager:', !Ref pythonFastApiTemplateclusterAuroraSecret, ":SecretString:username}}" ]]
99+
MasterUserPassword:
100+
!Join [ "", [ '{{resolve:secretsmanager:', !Ref pythonFastApiTemplateclusterAuroraSecret, ":SecretString:password}}" ]]
101+
DatabaseName: !Ref pythonFastApiTemplateclusterDBName
102+
Engine: 'aurora-mysql'
103+
EngineVersion: '5.7.mysql_aurora.2.07.1'
104+
EngineMode: serverless
105+
DBClusterParameterGroupName: !Ref pythonFastApiTemplateclusterDBClusterParameterGroup
106+
DBSubnetGroupName: !Ref pythonFastApiTemplateclusterDBSubnetGroup
107+
VpcSecurityGroupIds:
108+
- !Ref pythonFastApiTemplateclusterDBClusterSecurityGroup
109+
ScalingConfiguration:
110+
AutoPause: true
111+
# Replace "All" below with "!Ref Env" to set different autoscaling limits per environment.
112+
MinCapacity: !FindInMap [pythonFastApiTemplateclusterEnvScalingConfigurationMap, All, DBMinCapacity]
113+
MaxCapacity: !FindInMap [pythonFastApiTemplateclusterEnvScalingConfigurationMap, All, DBMaxCapacity]
114+
SecondsUntilAutoPause: !Ref pythonFastApiTemplateclusterDBAutoPauseSeconds
115+
pythonFastApiTemplateclusterSecretAuroraClusterAttachment:
116+
Type: AWS::SecretsManager::SecretTargetAttachment
117+
Properties:
118+
SecretId: !Ref pythonFastApiTemplateclusterAuroraSecret
119+
TargetId: !Ref pythonFastApiTemplateclusterDBCluster
120+
TargetType: AWS::RDS::DBCluster
121+
Outputs:
122+
pythonFastApiTemplateclusterSecret: # injected as pythonFastApiTemplateCLUSTER_SECRET environment variable by Copilot.
123+
Description: "The JSON secret that holds the database username and password. Fields are 'host', 'port', 'dbname', 'username', 'password', 'dbClusterIdentifier' and 'engine'"
124+
Value: !Ref pythonFastApiTemplateclusterAuroraSecret
125+
Export:
126+
Name: pythonFastApiTemplateclusterSecret
127+
pythonFastApiTemplateclusterSecurityGroup:
128+
Description: "The security group to attach to the workload."
129+
Value: !Ref pythonFastApiTemplateclusterSecurityGroup
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# The manifest for the "develop" environment.
2+
# Read the full specification for the "Environment" type at:
3+
# https://aws.github.io/copilot-cli/docs/manifest/environment/
4+
5+
# Your environment name will be used in naming your resources like VPC, cluster, etc.
6+
name: develop
7+
type: Environment
8+
9+
# Import your own VPC and subnets or configure how they should be created.
10+
# network:
11+
# vpc:
12+
# id:
13+
14+
# Configure the load balancers in your environment, once created.
15+
# http:
16+
# public:
17+
# private:
18+
19+
# Configure observability for your environment resources.
20+
observability:
21+
container_insights: false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# The manifest for the "python-fastapi-template-develop-svc" service.
2+
# Read the full specification for the "Load Balanced Web Service" type at:
3+
# https://aws.github.io/copilot-cli/docs/manifest/lb-web-service/
4+
5+
# Your service name will be used in naming your resources like log groups, ECS services, etc.
6+
name: python-fastapi-template-develop-svc
7+
type: Load Balanced Web Service
8+
# Distribute traffic to your service.
9+
http:
10+
# Requests to this path will be forwarded to your service.
11+
# To match all requests you can use the "/" path.
12+
path: '/'
13+
# You can specify a custom health check path. The default is "/".
14+
# healthcheck: '/'
15+
# Configuration for your containers and service.
16+
image:
17+
# Docker build arguments. For additional overrides: https://aws.github.io/copilot-cli/docs/manifest/lb-web-service/#image-build
18+
build: Dockerfile
19+
# Port exposed through your container to route traffic to it.
20+
port: 8000
21+
cpu: 256 # Number of CPU units for the task.
22+
memory: 512 # Amount of memory in MiB used by the task.
23+
count: 1 # Number of tasks that should be running in your service.
24+
exec: true # Enable running commands in your container.
25+
network:
26+
connect: true # Enable Service Connect for intra-environment traffic between services.
27+
secrets:
28+
PYTHON_FASTAPI_TEMPLATE_CLUSTER_SECRET:
29+
from_cfn: pythonFastApiTemplateclusterSecret
30+
# storage:
31+
# readonly_fs: true # Limit to read-only access to mounted root filesystems.
32+
33+
# Optional fields for more advanced use-cases.
34+
#
35+
#variables: # Pass environment variables as key value pairs.
36+
# LOG_LEVEL: info
37+
38+
#secrets: # Pass secrets from AWS Systems Manager (SSM) Parameter Store.
39+
# GITHUB_TOKEN: GITHUB_TOKEN # The key is the name of the environment variable, the value is the name of the SSM parameter.
40+
41+
# You can override any of the values defined above by environment.
42+
#environments:
43+
# test:
44+
# count: 2 # Number of tasks to run for the "test" environment.
45+
# deployment: # The deployment strategy for the "test" environment.
46+
# rolling: 'recreate' # Stops existing tasks before new ones are started for faster deployments.

0 commit comments

Comments
 (0)