mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Merge pull request #141 from Hestia-Homes/main
Updating fastapi lambda to use docker image as base
This commit is contained in:
commit
9013de72be
10 changed files with 128 additions and 50 deletions
|
|
@ -1 +1,13 @@
|
||||||
model_data/local_data/*
|
model_data/local_data/*
|
||||||
|
backend/tests/*
|
||||||
|
backend/node_modules/*
|
||||||
|
recommendations/tests/*
|
||||||
|
model_data/tests/*
|
||||||
|
infrastructure/*
|
||||||
|
data_collection/*
|
||||||
|
node_modules/*
|
||||||
|
conservation_areas/*
|
||||||
|
open_uprn/*
|
||||||
|
land_registry/*
|
||||||
|
pytest.ini
|
||||||
|
*/README.md
|
||||||
|
|
|
||||||
33
.github/workflows/deploy_fastapi_backend.yml
vendored
33
.github/workflows/deploy_fastapi_backend.yml
vendored
|
|
@ -59,16 +59,26 @@ jobs:
|
||||||
echo "::set-output name=db_port::${{ secrets[format('{0}_DB_PORT', github.ref_name)] }}"
|
echo "::set-output name=db_port::${{ secrets[format('{0}_DB_PORT', github.ref_name)] }}"
|
||||||
echo "::set-output name=db_name::${{ secrets[format('{0}_DB_NAME', github.ref_name)] }}"
|
echo "::set-output name=db_name::${{ secrets[format('{0}_DB_NAME', github.ref_name)] }}"
|
||||||
|
|
||||||
# - name: Build Lambda Layer
|
- name: Set ECR credentials
|
||||||
# run: |
|
id: set_ecr_credentials
|
||||||
# cd backend
|
run: |
|
||||||
# pip install -r requirements/lambda.txt -t python
|
echo "::set-output name=ecr_uri::${{ secrets[format('{0}_ECR_URI', github.ref_name)] }}"
|
||||||
# zip -r layer.zip python
|
|
||||||
#
|
- name: Setup Docker
|
||||||
# - name: Publish Lambda Layer
|
uses: docker/setup-buildx-action@v1
|
||||||
# run: |
|
|
||||||
# LAYER_ARN=$(aws lambda publish-layer-version --layer-name LambdaDependenciesLayer --zip-file fileb://backend/layer.zip | jq -r '.LayerVersionArn')
|
- name: Build Docker Image
|
||||||
# aws ssm put-parameter --name "/${{ github.ref_name }}/LambdaDependenciesLayerArn" --value "$LAYER_ARN" --type String --overwrite
|
run: |
|
||||||
|
docker build -t fastapi-lambda-image:${{ github.sha }} -f backend/docker/lambda.Dockerfile .
|
||||||
|
|
||||||
|
- name: Login to ECR
|
||||||
|
run: |
|
||||||
|
aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin ${{ steps.set_ecr_credentials.outputs.ecr_uri }}
|
||||||
|
|
||||||
|
- name: Tag and Push Docker Image to ECR
|
||||||
|
run: |
|
||||||
|
docker tag fastapi-lambda-image:${{ github.sha }} ${{ steps.set_ecr_credentials.outputs.ecr_uri }}:${{ github.sha }}
|
||||||
|
docker push ${{ steps.set_ecr_credentials.outputs.ecr_uri }}:${{ github.sha }}
|
||||||
|
|
||||||
- name: Deploy to AWS Lambda via Serverless
|
- name: Deploy to AWS Lambda via Serverless
|
||||||
env:
|
env:
|
||||||
|
|
@ -81,9 +91,10 @@ jobs:
|
||||||
DB_HOST: ${{ steps.set_db_credentials.outputs.db_host }}
|
DB_HOST: ${{ steps.set_db_credentials.outputs.db_host }}
|
||||||
DB_PORT: ${{ steps.set_db_credentials.outputs.db_port }}
|
DB_PORT: ${{ steps.set_db_credentials.outputs.db_port }}
|
||||||
DB_NAME: ${{ steps.set_db_credentials.outputs.db_name }}
|
DB_NAME: ${{ steps.set_db_credentials.outputs.db_name }}
|
||||||
|
ECR_URI: ${{ steps.set_ecr_credentials.outputs.ecr_uri }}
|
||||||
run: |
|
run: |
|
||||||
# Fetch database credentials from AWS Secrets Manager
|
# Fetch database credentials from AWS Secrets Manager
|
||||||
SECRET_VALUE=$(aws secretsmanager get-secret-value --secret-id dev/assessment_model/db_credentials --query SecretString)
|
SECRET_VALUE=$(aws secretsmanager get-secret-value --secret-id ${{ github.ref_name }}/assessment_model/db_credentials --query SecretString)
|
||||||
DB_USERNAME=$(echo "$SECRET_VALUE" | jq -r '. | fromjson | .db_assessment_model_username')
|
DB_USERNAME=$(echo "$SECRET_VALUE" | jq -r '. | fromjson | .db_assessment_model_username')
|
||||||
DB_PASSWORD=$(echo "$SECRET_VALUE" | jq -r '. | fromjson | .db_assessment_model_password')
|
DB_PASSWORD=$(echo "$SECRET_VALUE" | jq -r '. | fromjson | .db_assessment_model_password')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,11 @@ part of a larger application
|
||||||
|
|
||||||
# Folders
|
# Folders
|
||||||
|
|
||||||
|
### backend/
|
||||||
|
|
||||||
|
This folder contains the code for the fastapi backend service, which provides an interface to
|
||||||
|
much of the functionality in this repository, for the frontend
|
||||||
|
|
||||||
### model_data/
|
### model_data/
|
||||||
|
|
||||||
This folder contains related to the reading and preparation of
|
This folder contains related to the reading and preparation of
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,26 @@ FastAPI automatically generates interactive API documentation for your applicati
|
||||||
server and visit <yourlocalurl>/docs in your browser. Alternatively, you can go to
|
server and visit <yourlocalurl>/docs in your browser. Alternatively, you can go to
|
||||||
<yourlocalurl>/redoc to view the documentation in the ReDoc format.
|
<yourlocalurl>/redoc to view the documentation in the ReDoc format.
|
||||||
|
|
||||||
|
## Building the backend docker image locally
|
||||||
|
|
||||||
|
To build the backend docker image locally, run the following command from the root of the project directory:
|
||||||
|
|
||||||
|
```commandline
|
||||||
|
docker build -t fastapi-lambda-image:latest -f backend/docker/lambda.Dockerfile .
|
||||||
|
```
|
||||||
|
|
||||||
|
To check the size of the resulting image, run the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker images | grep fastapi-lambda-image
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a shell inside the Docker container to inspect its contents, run:
|
||||||
|
|
||||||
|
```commandline
|
||||||
|
docker run -it fastapi-lambda-image:latest /bin/bash
|
||||||
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
To run tests, run the following command from the root of the project directory:
|
To run tests, run the following command from the root of the project directory:
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,25 @@ ENV PYTHONUNBUFFERED 1
|
||||||
WORKDIR /Model
|
WORKDIR /Model
|
||||||
|
|
||||||
# Install system dependencies
|
# Install system dependencies
|
||||||
RUN apt-get update && apt-get install -y netcat-openbsd
|
RUN apt-get update && apt-get install -y netcat-openbsd
|
||||||
|
|
||||||
|
# Install python dependencies
|
||||||
|
COPY ./backend/requirements/base.txt ./backend/requirements/base.txt
|
||||||
|
RUN pip install --upgrade pip
|
||||||
|
# Install and clean up temp caches
|
||||||
|
RUN pip install -r backend/requirements/base.txt && rm -rf /root/.cache
|
||||||
|
|
||||||
|
# Copy project files
|
||||||
|
COPY ./backend/ ./backend
|
||||||
|
COPY ./recommendations/ ./recommendations
|
||||||
|
COPY ./model_data/BaseUtility.py ./model_data/BaseUtility.py
|
||||||
|
COPY ./model_data/config.py ./model_data/config.py
|
||||||
|
COPY ./model_data/optimiser/ ./model_data/optimiser/
|
||||||
|
COPY ./model_data/__init__.py ./model_data/__init__.py
|
||||||
|
COPY ./model_data/EpcClean.py ./model_data/EpcClean.py
|
||||||
|
COPY ./model_data/utils.py ./model_data/utils.py
|
||||||
|
COPY ./model_data/epc_attributes/ ./model_data/epc_attributes/
|
||||||
|
COPY ./datatypes/ ./datatypes/
|
||||||
|
|
||||||
|
# Define the handler location
|
||||||
|
CMD ["backend.app.main.handler"]
|
||||||
|
|
|
||||||
|
|
@ -98,4 +98,10 @@ module "route53" {
|
||||||
providers = {
|
providers = {
|
||||||
aws.aws_use1 = aws.aws_use1
|
aws.aws_use1 = aws.aws_use1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Create an ECR repository for storage of the lambda's docker images
|
||||||
|
module "ecr" {
|
||||||
|
source = "./modules/ecr"
|
||||||
|
environment = var.stage
|
||||||
|
}
|
||||||
|
|
|
||||||
29
infrastructure/terraform/modules/ecr/main.tf
Normal file
29
infrastructure/terraform/modules/ecr/main.tf
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
resource "aws_ecr_repository" "my_repository" {
|
||||||
|
name = "fastapi-repository-${var.environment}"
|
||||||
|
image_tag_mutability = "MUTABLE" # Allows overwriting image tags, change to IMMUTABLE if you want to prevent overwriting
|
||||||
|
|
||||||
|
image_scanning_configuration {
|
||||||
|
scan_on_push = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_ecr_lifecycle_policy" "my_repository_policy" {
|
||||||
|
repository = aws_ecr_repository.my_repository.name
|
||||||
|
|
||||||
|
policy = jsonencode({
|
||||||
|
rules = [
|
||||||
|
{
|
||||||
|
rulePriority = 1
|
||||||
|
description = "Retain only the last 10 images"
|
||||||
|
selection = {
|
||||||
|
tagStatus = "any"
|
||||||
|
countType = "imageCountMoreThan"
|
||||||
|
countNumber = 10
|
||||||
|
}
|
||||||
|
action = {
|
||||||
|
type = "expire"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
4
infrastructure/terraform/modules/ecr/outputs.tf
Normal file
4
infrastructure/terraform/modules/ecr/outputs.tf
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
output "ecr_repository_name" {
|
||||||
|
description = "Name of the EPR repo in AWS"
|
||||||
|
value = aws_ecr_repository.my_repository.name
|
||||||
|
}
|
||||||
4
infrastructure/terraform/modules/ecr/variables.tf
Normal file
4
infrastructure/terraform/modules/ecr/variables.tf
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
variable "environment" {
|
||||||
|
description = "The environment for the ECR repository (dev or prod)"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,6 @@ service: fastapi-lambda
|
||||||
|
|
||||||
provider:
|
provider:
|
||||||
name: aws
|
name: aws
|
||||||
runtime: python3.10
|
|
||||||
region: eu-west-2
|
region: eu-west-2
|
||||||
architecture: x86_64
|
architecture: x86_64
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -17,6 +16,7 @@ provider:
|
||||||
DB_USERNAME: ${env:DB_USERNAME}
|
DB_USERNAME: ${env:DB_USERNAME}
|
||||||
DB_PASSWORD: ${env:DB_PASSWORD}
|
DB_PASSWORD: ${env:DB_PASSWORD}
|
||||||
DB_PORT: ${env:DB_PORT}
|
DB_PORT: ${env:DB_PORT}
|
||||||
|
ECR_URI: ${env:ECR_URI}
|
||||||
# Give lambda access to read from the bucket
|
# Give lambda access to read from the bucket
|
||||||
iam:
|
iam:
|
||||||
role:
|
role:
|
||||||
|
|
@ -31,46 +31,11 @@ provider:
|
||||||
- arn:aws:s3:::${env:PLAN_TRIGGER_BUCKET}/*
|
- arn:aws:s3:::${env:PLAN_TRIGGER_BUCKET}/*
|
||||||
|
|
||||||
|
|
||||||
package:
|
|
||||||
individually: true
|
|
||||||
patterns:
|
|
||||||
- 'backend/**'
|
|
||||||
- '!backend/tests/**'
|
|
||||||
- 'recommendations/**'
|
|
||||||
- '!recommendations/tests/**'
|
|
||||||
# Exclude all of model_data but then re-include the files we need
|
|
||||||
- '!model_data/**'
|
|
||||||
- 'model_data/BaseUtility.py'
|
|
||||||
- 'model_data/config.py'
|
|
||||||
- 'model_data/optimiser/**'
|
|
||||||
- 'model_data/__init__.py'
|
|
||||||
- 'model_data/EpcClean.py'
|
|
||||||
- 'model_data/utils.py'
|
|
||||||
- 'model_data/epc_attributes/**'
|
|
||||||
- 'datatypes/**'
|
|
||||||
- '!infrastructure/**'
|
|
||||||
- '!data_collection/**'
|
|
||||||
- '!node_modules/**'
|
|
||||||
- '!conservation_areas/**'
|
|
||||||
- '!open_uprn/**'
|
|
||||||
- '!land_registry/**'
|
|
||||||
- '!pytest.ini'
|
|
||||||
- '**/README.md'
|
|
||||||
|
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
- serverless-python-requirements
|
- serverless-python-requirements
|
||||||
- serverless-domain-manager
|
- serverless-domain-manager
|
||||||
|
|
||||||
custom:
|
custom:
|
||||||
pythonRequirements:
|
|
||||||
dockerizePip: true
|
|
||||||
dockerFile: backend/docker/lambda.Dockerfile
|
|
||||||
useDocker: true
|
|
||||||
dockerSsh: true
|
|
||||||
fileName: backend/requirements/base.txt
|
|
||||||
dockerBuildCmdExtraArgs:
|
|
||||||
- '--progress=plain'
|
|
||||||
customDomain:
|
customDomain:
|
||||||
domainName: api.${self:provider.environment.DOMAIN_NAME}
|
domainName: api.${self:provider.environment.DOMAIN_NAME}
|
||||||
createRoute53Record: true
|
createRoute53Record: true
|
||||||
|
|
@ -78,7 +43,8 @@ custom:
|
||||||
|
|
||||||
functions:
|
functions:
|
||||||
app:
|
app:
|
||||||
handler: backend.app.main.handler
|
image:
|
||||||
|
uri: ${env:ECR_URI}:latest
|
||||||
events:
|
events:
|
||||||
- http:
|
- http:
|
||||||
path: /{proxy+}
|
path: /{proxy+}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue