FastAPI
FastAPI is a modern, async web-framework for building APIs with Python 3.6+ making use of type hints. It is a microframework, in many ways quite similar to Flask and uses the MIT license.
Note
For this guide you should be familiar with the basic concepts of
Installation
We are creating a very basic proof-of-concept API that will do a calculation and return the result as valid JSON.
Create application directory and files
[isabell@stardust ~]$ mkdir ~/fastapi
[isabell@stardust ~]$
Create a file ~/fastapi/main.py
with the following content:
#!/usr/bin/env python3.11
import fastapi
import uvicorn
api = fastapi.FastAPI()
@api.get('/')
def calculate():
answer = 24 + 18
return {'answer': answer}
# To test this app locally, uncomment this line:
# uvicorn.run(api, host="localhost", port=8000)
Python Virtual Environment
To install the packages your application depends on, you want to use a virtual environment that is isolated from the system’s Python packages. FastAPI requires Python 3.6+ but we are going to use the latest version available, which is currently Python 3.11:
[isabell@stardust ~]$ cd ~/fastapi
[isabell@stardust fastapi]$ python3.11 -m venv venv
[isabell@stardust fastapi]$ source venv/bin/activate
(venv) [isabell@stardust fastapi]$
In your virtual environment, install the dependencies we are using in main.py
:
(venv) [isabell@stardust fastapi]$ pip install fastapi uvicorn
(venv) [isabell@stardust fastapi]$
Note
You can already check if your application is working by uncommenting the ucivorn.run()
line and executing python main.py
in the virtual environment. Open a second ssh connection and get the output with curl localhost:8000
While uvicorn handles the asynchronous side of FastAPI, we want gunicorn as a well-tested and production-ready solution to run and manage multiple uvicorn workers. Install it with two dependencies in your virtual environment:
(venv) [isabell@stardust fastapi]$ pip install gunicorn uvloop httptools
(venv) [isabell@stardust fastapi]$
You can deactivate the virtual environment context like this:
(venv) [isabell@stardust fastapi]$ deactivate
[isabell@stardust fastapi]$
Configuration
Incoming https requests are routed through nginx to a web backend where our application server is listening. Let’s get this working:
Gunicorn
First, we are telling gunicorn to spin up several uvicorn processes and listen on port 8000 for incoming requests. Create the config file ~/fastapi/conf.py
:
import os
app_path = os.environ['HOME'] + '/fastapi'
# Gunicorn configuration
wsgi_app = 'main:api'
bind = ':8000'
chdir = app_path
workers = 4
worker_class = 'uvicorn.workers.UvicornWorker'
errorlog = app_path + '/errors.log'
This is a minimal working example based on gunicorn’s example config, you can find a comprehensive list of options here.
Note
Test if everything is working with ~/fastapi/venv/bin/gunicorn --config ~/fastapi/conf.py --check-config
. If there is no output, you’re good.
Supervisord
Next, create a configuration for supervisord in ~/etc/services.d/fastapi.ini
:
[program:fastapi]
directory=%(ENV_HOME)s/fastapi
command=%(ENV_HOME)s/fastapi/venv/bin/gunicorn --config %(ENV_HOME)s/fastapi/conf.py
After creating the configuration, tell supervisord to refresh its configuration and start the service:
[isabell@stardust ~]$ supervisorctl reread
SERVICE: available
[isabell@stardust ~]$ supervisorctl update
SERVICE: added process group
[isabell@stardust ~]$ supervisorctl status
SERVICE RUNNING pid 26020, uptime 0:03:14
[isabell@stardust ~]$
Web backend
Note
Gunicorn is set up to run on port 8000.
To make the application accessible from the outside, configure a web backend:
[isabell@stardust ~]$ uberspace web backend set / --http --port <port>
Set backend for / to port <port>; please make sure something is listening!
You can always check the status of your backend using "uberspace web backend list".
[isabell@stardust ~]$
That’s it
This concludes the setup. Point your browser to your url and check that everything is running correctly.
Written by: Christian Macht <https://github.com/cmacht/>