Python Cloud Deployment ā AWS, GCP & Serverless
Cloud deployment makes your Python apps accessible from anywhere with automatic scaling. This tutorial covers serverless deployment, container platforms, and CI/CD pipelines.
Learning Objectives
- Deploy to AWS Lambda with Mangum
- Use Google Cloud Functions
- Configure CI/CD pipelines with GitHub Actions
- Manage cloud resources with boto3
What is Cloud Deployment?
Local Development Cloud Deployment
āāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Your Laptop ā ā Cloud (AWS/GCP/Azure) ā
ā ā ā ā
ā main.py ā āāāāŗ ā āāāāāāāāāāāāāāāāāāāā ā
ā app.db ā ā ā Lambda/Cloud Run ā ā
ā config.env ā ā ā (auto-scaling) ā ā
ā ā ā āāāāāāāāāāāāāāāāāāāā ā
ā localhost ā ā Users worldwide access ā
āāāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāāāāāāāāāāā
Serverless means you don't manage servers. You upload your code, and the cloud provider runs it, scales it, and charges you only for actual usage.
AWS Lambda with FastAPI
AWS Lambda runs Python functions in response to events (HTTP requests, file uploads, scheduled tasks). Mangum bridges FastAPI and Lambda.
Step 1: Install Dependencies
pip install fastapi mangum
Step 2: Write Your API
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.get("/")
def root():
return {"message": "Hello from AWS Lambda"}
@app.post("/items")
def create_item(item: Item):
return {"status": "created", "item": item}
@app.get("/items/{item_id}")
def get_item(item_id: int):
return {"item_id": item_id, "name": "Sample Item"}
Step 3: Create Lambda Handler
# handler.py
from mangum import Mangum
from main import app
# Mangum adapts FastAPI for Lambda
handler = Mangum(app)
# Lambda sends events like this:
# {
# "httpMethod": "GET",
# "path": "/items/42",
# "headers": {...},
# "body": null
# }
#
# Mangum converts this to a FastAPI request,
# runs your route, and converts the response back.
Step 4: Deploy with AWS CLI
# Install AWS CLI
pip install awscli
aws configure # Set up credentials
# Create deployment package
zip -r function.zip . -x "*.git*" "__pycache__/*"
# Create Lambda function
aws lambda create-function \
--function-name my-fastapi \
--runtime python3.11 \
--handler handler.handler \
--zip-file fileb://function.zip \
--role arn:aws:iam::YOUR_ACCOUNT:role/lambda-role \
--timeout 30 \
--memory-size 256
# Create API Gateway trigger
aws apigateway create-rest-api --name "my-api"
# (Configure routes to point to Lambda)
Google Cloud Functions
# main.py
def hello_world(request):
"""Handle HTTP request."""
request_json = request.get_json()
if request_json and 'name' in request_json:
name = request_json['name']
else:
name = "World"
return f"Hello, {name}!"
# Deploy
gcloud functions deploy hello-world \
--runtime python311 \
--trigger-http \
--allow-unauthenticated
CI/CD with GitHub Actions
# .github/workflows/deploy.yml
name: Deploy to AWS
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest tests/ -v
- name: Run type check
run: mypy src/
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy to Lambda
uses: appleboy/lambda-action@v1.0.0
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
region: us-east-1
function_name: my-fastapi
zip_file: function.zip
How CI/CD Works
Push to GitHub
ā
ā¼
āāāāāāāāāāāāāāā
ā Run Tests ā āāā pytest, mypy, linting
āāāāāāāā¬āāāāāāā
ā Tests pass
ā¼
āāāāāāāāāāāāāāā
ā Deploy ā āāā Package and upload to cloud
āāāāāāāā¬āāāāāāā
ā
ā¼
āāāāāāāāāāāāāāā
ā Live! ā āāā Users can access the new version
āāāāāāāāāāāāāāā
Managing Cloud Resources with boto3
import boto3
# S3 ā File Storage
s3 = boto3.client('s3')
s3.upload_file('local_file.txt', 'my-bucket', 'remote_file.txt')
s3.download_file('my-bucket', 'remote_file.txt', 'downloaded.txt')
# DynamoDB ā NoSQL Database
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Users')
table.put_item(Item={'id': '1', 'name': 'Alice'})
response = table.get_item(Key={'id': '1'})
Key Takeaways
- Lambda is great for event-driven, short-running tasks
- Use Mangum to run FastAPI on Lambda
- Package dependencies with your code in zip file
- Use GitHub Actions for automated testing and deployment
- Store secrets in AWS Secrets Manager, not in code
- Monitor with CloudWatch or Cloud Logging
- Start with serverless ā scale to containers if needed