/flask-lambda-template

Flask + Lambda + APIGateway Template

Primary LanguageVue

Serverless-CMS

Constructed by

  • Serverside:
    • Flask + Lambda + APIGateway (deploy by Serverless Framework)
    • DynamoDB
  • Frontend: VueJS

Instration

Preparation

You need below

  • common
    • aws-cli >= 1.18.X
    • Terraform >= 0.14.5
  • serverless
    • nodeJS >= 18.16.X
    • Python >= 3.10.X
  • frontend
    • nodeJS >= v14.15.X

Install tools

Install serverless, python venv and terraform on mac

# At project root dir
cd (project_root/)serverless
npm install -g serverless
python3 -m venv .venv

brew install tfenv
tfenv install 0.14.5
tfenv use 0.14.5

Install Packages

Install npm packages

# At project root dir
cd (project_root/)serverless
npm install

Install python packages

. .venv/bin/activate
pip install -r requirements.txt

Use Contact component

If use Contact component, execute bellow

. .venv/bin/activate
pip install -r pytz Flask-WTF

Deploy AWS Resources by Terraform

Create AWS S3 Bucket for terraform state and frontend config

Create S3 Buckets like below in ap-northeast-1 region

  • your-serverless-deployment
    • Store deployment state files by terraformand and serverless framework
    • Create directory "terraform/your-project-name"
  • your-serverless-configs
    • Store config files for app
    • Create directory "your-project-name/frontend/prd" and "your-project-name/frontend/dev"

1. Edit Terraform config file

Copy sample file and edit variables for your env

cd (project_root_dir)/terraform
cp terraform.tfvars.sample terraform.tfvars
vi terraform.tfvars
prj_prefix = "your-porject-name"
 ...
route53_zone_id        = "Set your route53 zone id"
domain_api_prd         = "your-domain-api.example.com"
domain_api_dev         = "your-domain-api-dev.example.com"
domain_static_site_prd = "your-domain-static.example.com"
domain_static_site_dev = "your-domain-static-dev.example.com"
domain_media_site_prd  = "your-domain-media.example.com"
domain_media_site_dev  = "your-domain-media-dev.example.com"

2. Set AWS profile name to environment variable

export AWS_SDK_LOAD_CONFIG=1
export AWS_PROFILE=your-aws-profile-name
export AWS_REGION="ap-northeast-1"

3. Execute terraform init

Command Example to init

terraform init -backend-config="bucket=your-deployment" -backend-config="key=terraform/your-project/terraform.tfstate" -backend-config="region=ap-northeast-1" -backend-config="profile=your-aws-profile-name"

4. Execute terraform apply

terraform apply -auto-approve -var-file=./terraform.tfvars

5. Create Admin User

Create Admin User by aws-cli

export AWS_SDK_LOAD_CONFIG=1
export AWS_PROFILE=your-aws-profile-name
export AWS_DEFAULT_REGION="ap-northeast-1"

aws cognito-idp admin-create-user \
--user-pool-id ap-northeast-1_xxxxxxxxx \
--username your-username \
--user-attributes \
  Name=email,Value=sample@example.com \
  Name=email_verified,Value=True \
  Name=custom:role,Value=admin \
  Name=custom:acceptServiceIds,Value=hoge \
--desired-delivery-mediums EMAIL

You get temporary password by email Update password as parmanent

aws cognito-idp admin-set-user-password \
--user-pool-id ap-northeast-1_xxxxxxxxx \
--username your-username \
--password 'your-parmanent-password' \
--permanent

6. Set CORS of media file bucket

  • Access to S3 console of media file bucket
  • Select tab "Permission"
  • Press "Edit" button of "Cross-origin resource sharing (CORS)"
  • Set bellow
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT",
            "POST",
            "DELETE",
            "GET"
        ],
        "AllowedOrigins": [
            "https://your-domain.example.com"
        ],
        "ExposeHeaders": []
    }
]

DynamoDB Backup Settings

If you want to backup DynamoDB items, set bellows

  • Access to "AWS Backup" on AWS Console and set region
  • Press "Create backup plan"
  • Input as follows for "Plan"
    • Start options
      • Select "Build a new plan"
      • Backup plan name: your-project-dynamodb-backup
    • Backup rule configuration
      • Backup vault: Default
      • Backup rule name: your-project-dynamodb-backup-rule
      • Backup frequency: Daily
      • Backup window: Customize backup window
      • Backup window settings: as you like
    • Press "Create backup plan"
  • Input as follows for "Assign resources"
    • General
      • Resource assignment name: your-project-dynamodb-backup-assignment
      • IAM role: Default role
    • Resource selection
        1. Define resource selection: Include specific resource types
        1. Select specific resource types: DynamoDB
        • Table names: All tables
        1. Refine selection using tags
        • Key: backup
        • Condition for value: Eauqls
        • Value: aws-backup
    • Press "Assign resources"

Deploy Server Side Resources

Setup configs

Setup config files per stage

cd (project_root/)serverless
cp -r config/stages-sample config/stages
vi config/stages/*
# config/stages/common.yml

service: 'your-project-name'
awsAccountId: 'your-aws-acconnt-id'
defaultRegion: 'ap-northeast-1'
deploymentBucketName: 'your-serverless-deployment'
 ...
# config/stages/prd.yml
# config/stages/dev.yml

domainName: your-domain-api.example.com
corsAcceptOrigins: 'https://your-domain.example.com'
notificationEmail: admin@example.com
 ...
mediaS3BucketName: "your-domain-media.example.com"
 ...
commentImportS3BucketName: "your-content-resources"
commentImportS3BucketPath: "your-project/prd/comments"
 ...

Create Domains for API

Execute below command

cd (project_root/)serverless
export AWS_SDK_LOAD_CONFIG=1
export AWS_PROFILE="your-profile-name"
export AWS_REGION="ap-northeast-1"

sls create_domain # Deploy for dev

If deploy for prod

sls create_domain --stage prd # Deploy for prod

Deploy to Lambda

Execute below command

cd (project_root/)serverless
export AWS_SDK_LOAD_CONFIG=1
export AWS_PROFILE="your-profile-name"
export AWS_REGION="ap-northeast-1"

sls deploy # Deploy for dev

If deploy for prod

sls deploy --stage prd # Deploy for prod

Save default ServiceId on DynamoDB

  1. Open DynamoDB page on AWS console
  2. Click Tables > Explore items
  3. Select "your-prefix-stage-service"
  4. Click "Create item"
  5. Select "JSON"
  6. Input below, and create
{
  "serviceId": {
    "S": "hoge"
  },
  "label": {
    "S": "ほげ"
  }
}

Deploy Frontend Resources

Setup about TinyMCE Editor

Set enviroment variables

  • Access to https://github.com/{your-account}/{repository-name}/settings/secrets/actions
  • Push "New repository secret"
  • Add Below
    • Common
      • AWS_ACCESS_KEY_ID : your-aws-access_key
      • AWS_SECRET_ACCESS_KEY : your-aws-secret_key
    • For Production
      • CLOUDFRONT_DISTRIBUTION : your cloudfront distribution created by terraform for production
      • S3_CONFIG_BUCKET: "your-serverles-configs/your-project/frontend/prd" for production
      • S3_RESOURCE_BUCKET: "your-domain-static-site.example.com" for production
    • For Develop
      • CLOUDFRONT_DISTRIBUTION_DEV : your cloudfront distribution created by terraform for develop
      • S3_CONFIG_BUCKET_DEV: "your-serverles-configs/your-project/frontend/dev" for develop
      • S3_RESOURCE_BUCKET_DEV: "your-domain-static-site-dev.example.com" for develop

Upload config file for frontend app

Edit config file

Basic config

cd (project_root_dir/)frontend
cp src/config/config.json.sample src/config/config.json
vi src/config/config.json
{
  "domain": "your-domain-api.example.com",
  "port": null,
  "baseUrl": "/",
  "isSSL": true,
 ...
  "media": {
    "url": "https://your-domain-media.example.com",
 ...
  },
  "tinyMCEApiKey": "your-tinyMCE-api-key"
}

AWS Cognito config (If use admin functions)

cp src/config/cognito-client-config.json.sample src/config/cognito-client-config.json
vi src/config/cognito-client-config.json
{
  "Region": "ap-northeast-1",
  "UserPoolId": "ap-northeast-1_xxxxxxxxx",
  "ClientId": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "IdentityPoolId": "ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

Upload S3 Bucket "your-serverless-configs/your-project-name/frontend/{stage}"

Deploy continually on pushed to git

Development

Local Development

Install packages for development

cd (project_root/)serverless
. .venv/bin/activate
pip install pylint

Work on local

Set venv

cd (project_root/)serverless
. .venv/bin/activate

Create Docker container only for the first time

cd (project_root/)serverless
docker-compose build

Start DynamoDB Local on Docker

cd (project_root)/serverless/develop/
docker-compose up -d

DynamomDB setup

cd (project_root/)serverless
sls dynamodb start

Execute below command

cd (project_root/)serverless
sls wsgi serve

Request http://127.0.0.1:5000

If you want to stop DynamoDB Local on Docker

cd (project_root)/serverless/develop/
docker-compose stop

Execute Script

cd (project_root/)serverless
sls invoke local --function funcName --data param

Convert existing DB records to DynamoDB

Install packages for converter if use MySQL for convert target service

cd (project_root/)serverless
. .venv/bin/activate
pip install PyMySQL

Set converter of target service

cd (root/)serverless/develop/db_converter/services/
git clone {repository url of target service converter}

Execute converter

cd (root/)serverless/develop/db_converter
python main.py {service_name}

Performance Test

Setup K6

Install for macOS

brew install k6

Execute

k6 run ./dev_tools/performance/vote.js --vus NN --duration MMs

Destroy Resources

Destroy for serverless resources

cd (project_root/)serverless
sls remove --stage Target-stage
sls delete_domain --stage Target-stage

Removed files in S3 Buckets named "your-domain.example.com-cloudfront-logs" and "your-domain.example.com"

Destroy for static server resources by Terraform

cd (project_root/)terraform
terraform destroy -auto-approve -var-file=./terraform.tfvars