FastAPI Azure Deployment
Introduction
Deploying your FastAPI application to a cloud provider like Microsoft Azure allows you to make your API available to users worldwide with high reliability and scalability. Azure offers multiple services for hosting web applications, and in this guide, we'll walk through the process of deploying a FastAPI application to Azure App Service, one of the most straightforward deployment options.
By the end of this tutorial, you'll understand:
- What Azure App Service is and why it's suitable for FastAPI
- How to prepare your FastAPI app for Azure deployment
- Step-by-step deployment process using different methods
- How to monitor and troubleshoot your deployed application
Prerequisites
Before we begin, make sure you have:
- A FastAPI application ready for deployment
- A Microsoft Azure account (you can create a free account if needed)
- Azure CLI installed on your machine
- Git for version control
- Python 3.6 or higher installed locally
Understanding Azure App Service
Azure App Service is a fully managed platform for building, deploying, and scaling web apps. It supports multiple programming languages, including Python, and provides built-in infrastructure maintenance, security patching, and scaling.
Key benefits for FastAPI deployment:
- Built-in support for Python: Run your FastAPI app without complex configuration
- Easy scaling: Adjust resources as your traffic grows
- Continuous deployment: Connect to GitHub for automatic deployments
- Managed SSL certificates: Secure your API endpoints
- Custom domains: Use your own domain name
Preparing Your FastAPI App for Azure
Before deployment, we need to structure our FastAPI app correctly for Azure App Service:
1. Project Structure
A typical project structure should look like:
my-fastapi-app/
├── app/
│ ├── __init__.py
│ ├── main.py # Your FastAPI application
│ ├── routers/ # API routes
│ └── models/ # Data models
├── requirements.txt
└── startup.txt # For Azure
2. Ensure Your main.py Is Properly Set Up
Your main FastAPI file should expose the app object. Here's a simple example:
from fastapi import FastAPI
import uvicorn
app = FastAPI(title="My API", description="Deployed on Azure")
@app.get("/")
async def root():
return {"message": "Hello World from Azure!"}
@app.get("/health")
async def health():
return {"status": "healthy"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
3. Create Requirements File
Make sure your requirements.txt
file includes all dependencies:
fastapi==0.95.0
uvicorn==0.21.1
gunicorn==20.1.0
python-multipart==0.0.6
# Add other dependencies your app needs
4. Create Startup Command File
Create a file named startup.txt
in your project root with the following content:
gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:app
This tells Azure how to start your FastAPI application.
Deploying to Azure App Service
Let's go through the deployment process step by step:
Method 1: Using Azure Portal
-
Create a Web App in Azure Portal:
- Log into the Azure Portal
- Click "Create a resource" > "Web App"
- Fill in the basic details:
- Resource Group: Create new or select existing
- Name: Choose a unique name (e.g.,
my-fastapi-app
) - Publish: Code
- Runtime stack: Python 3.9 or higher
- Operating System: Linux
- Region: Choose the closest to your users
- Click "Review + create" and then "Create"
-
Configure deployment settings:
- Once the web app is created, go to its dashboard
- Navigate to "Settings" > "Configuration"
- In "General settings", set:
- Stack: Python
- Startup Command:
gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:app
- Click "Save"
-
Deploy your code:
- Go to "Deployment Center"
- Choose your source (GitHub, Azure Repos, or Local Git)
- Follow the wizard to connect your repository
- Once connected, Azure will deploy your application
Method 2: Using Azure CLI
For a more streamlined approach, you can use the Azure CLI:
- Login to Azure:
az login
- Create a resource group:
az group create --name FastAPIResourceGroup --location eastus
- Create an App Service plan:
az appservice plan create --name FastAPIAppPlan --resource-group FastAPIResourceGroup --sku B1 --is-linux
- Create a web app:
az webapp create --resource-group FastAPIResourceGroup --plan FastAPIAppPlan --name my-fastapi-app --runtime "PYTHON|3.9"
- Configure the startup command:
az webapp config set --resource-group FastAPIResourceGroup --name my-fastapi-app --startup-file "gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:app"
- Deploy your code using Git:
az webapp deployment source config-local-git --name my-fastapi-app --resource-group FastAPIResourceGroup
- Get the Git deployment URL:
az webapp deployment list-publishing-credentials --name my-fastapi-app --resource-group FastAPIResourceGroup --query scmUri --output tsv
- Add the Azure remote to your local Git:
git remote add azure <URL-from-previous-step>
- Push your code to Azure:
git push azure main
Advanced Configuration
Environment Variables
To add environment variables (for API keys, database connections, etc.):
- In the Azure Portal, go to your App Service
- Navigate to "Settings" > "Configuration" > "Application settings"
- Click "+ New application setting"
- Add your key-value pairs
- Click "Save"
In your FastAPI code, access these as environment variables:
import os
from fastapi import FastAPI
app = FastAPI()
DATABASE_URL = os.environ.get("DATABASE_URL")
@app.get("/")
async def root():
return {"database_configured": DATABASE_URL is not None}
Custom Domain and HTTPS
To add a custom domain and enable HTTPS:
- In the Azure Portal, go to your App Service
- Navigate to "Settings" > "Custom domains"
- Click "+ Add custom domain"
- Follow the instructions to verify your domain
- Once added, click on the domain and select "Add binding" to add an SSL certificate
Scaling Your App
To scale your FastAPI application:
- In Azure Portal, go to your App Service
- Navigate to "Settings" > "Scale up (App Service plan)" to increase VM size
- Or go to "Scale out" to increase the number of instances
Real-world Example: A FastAPI Todo API on Azure
Let's deploy a more practical example—a simple Todo API with Azure Database for PostgreSQL:
- Create a PostgreSQL database in Azure:
az postgres server create --resource-group FastAPIResourceGroup --name my-fastapi-postgres --location eastus --admin-user myuser --admin-password MyPassword123! --sku-name B_Gen5_1
- Create the Todo API app:
# app/main.py
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
from typing import List, Optional
import os
import databases
import sqlalchemy
DATABASE_URL = os.environ.get("DATABASE_URL")
database = databases.Database(DATABASE_URL)
metadata = sqlalchemy.MetaData()
todos = sqlalchemy.Table(
"todos",
metadata,
sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
sqlalchemy.Column("title", sqlalchemy.String),
sqlalchemy.Column("completed", sqlalchemy.Boolean),
)
class TodoIn(BaseModel):
title: str
completed: bool = False
class Todo(BaseModel):
id: int
title: str
completed: bool
app = FastAPI(title="Todo API")
@app.on_event("startup")
async def startup():
await database.connect()
@app.on_event("shutdown")
async def shutdown():
await database.disconnect()
@app.post("/todos/", response_model=Todo)
async def create_todo(todo: TodoIn):
query = todos.insert().values(title=todo.title, completed=todo.completed)
last_record_id = await database.execute(query)
return {**todo.dict(), "id": last_record_id}
@app.get("/todos/", response_model=List[Todo])
async def read_todos():
query = todos.select()
return await database.fetch_all(query)
@app.get("/todos/{todo_id}", response_model=Todo)
async def read_todo(todo_id: int):
query = todos.select().where(todos.c.id == todo_id)
todo = await database.fetch_one(query)
if todo is None:
raise HTTPException(status_code=404, detail="Todo not found")
return todo
@app.put("/todos/{todo_id}", response_model=Todo)
async def update_todo(todo_id: int, todo: TodoIn):
query = todos.update().where(todos.c.id == todo_id).values(title=todo.title, completed=todo.completed)
await database.execute(query)
return {**todo.dict(), "id": todo_id}
@app.delete("/todos/{todo_id}", response_model=dict)
async def delete_todo(todo_id: int):
query = todos.delete().where(todos.c.id == todo_id)
await database.execute(query)
return {"message": "Todo deleted successfully"}
- Update requirements.txt:
fastapi==0.95.0
uvicorn==0.21.1
gunicorn==20.1.0
databases[postgresql]==0.7.0
sqlalchemy==1.4.46
psycopg2-binary==2.9.5
-
Deploy to Azure as shown earlier
-
Add the DATABASE_URL environment variable in Azure portal:
postgresql://myuser:[email protected]:5432/postgres
Monitoring and Troubleshooting
After deployment, monitor your application:
-
View logs:
- In Azure Portal, go to your App Service
- Navigate to "Monitoring" > "Log stream" to see real-time logs
-
Set up Application Insights:
- In Azure Portal, go to your App Service
- Navigate to "Settings" > "Application Insights"
- Click "Turn on Application Insights"
-
Configure logging in your FastAPI app:
import logging
from fastapi import FastAPI, Request
app = FastAPI()
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("uvicorn")
@app.middleware("http")
async def log_requests(request: Request, call_next):
logger.info(f"Request: {request.method} {request.url}")
response = await call_next(request)
logger.info(f"Response status: {response.status_code}")
return response
@app.get("/error-test")
async def create_error():
try:
# Simulate error
1/0
except Exception as e:
logger.error(f"An error occurred: {str(e)}")
return {"error": str(e)}
Common Issues and Solutions
-
Application not starting:
- Check your startup command
- Ensure all dependencies are in requirements.txt
- Look at the logs for error messages
-
Database connection issues:
- Verify environment variables are set correctly
- Check that the Azure PostgreSQL firewall allows connections from Azure services
-
Performance issues:
- Consider scaling up your App Service plan
- Enable Application Insights to identify bottlenecks
Summary
In this guide, we've covered how to deploy a FastAPI application to Azure App Service. We started with the basics, including preparing your app structure, creating the necessary Azure resources, and deploying using different methods. We then explored advanced topics like environment variables, custom domains, and database integration, and finished with monitoring and troubleshooting techniques.
Azure App Service provides a robust platform for hosting FastAPI applications, with features that support all stages of your application lifecycle, from development to production.
Additional Resources
- FastAPI Official Documentation
- Azure App Service Documentation
- Azure Python Developer Center
- GitHub Actions for Azure deployment
Exercises
- Deploy a basic FastAPI application to Azure App Service using the Azure CLI.
- Add a custom domain to your deployed FastAPI application.
- Implement environment-specific configuration for development and production environments.
- Create a CI/CD pipeline using GitHub Actions to automatically deploy your FastAPI app to Azure when you push to main.
- Add Application Insights to your FastAPI application and analyze the performance metrics.
Happy deploying!
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)