.. author:: Christian Macht <https://github.com/cmacht/>
.. tag:: lang-python
.. tag:: web
.. tag_list::
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
We are creating a very basic proof-of-concept API that will do a calculation and return the result as valid JSON.
[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)
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]$
Incoming https requests are routed through :manual:`nginx <background-http-stack>` to a :manual:`web backend <web-backends>` where our application server is listening. Let's get this working:
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.
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
Note
Gunicorn is set up to run on port 8000.
This concludes the setup. Point your browser to :manual:`your url <web-domains>` and check that everything is running correctly.
.. author_list::