In my previous blog post, we created a simple FastAPI-based greeting service with both GET
and POST
endpoints, an HTML frontend, and interactive documentation. In this follow-up blog post we’ll deploy it to the cloud so it can be accessed publicly using Render. I have no affiliation with them, but chose their platform because they offer a generous free tier.
You’ll learn how to:
- Turn the Jupyter Notebook (my go-to tool for rapid prototyping) into a standalone Python file
- Capture your app’s dependencies in a
requirements.txt
file - Test your app locally in a virtual environment
- Deploy the app to Render (but feel free to use any other cloud provider you like)
In short, we’ll take the FastAPI greeting service from “it works on my machine” to “live on the internet.” 🤓
Creating a Local Deployment
Once you’re done developing your FastAPI app in a Jupyter Notebook, you can prepare it for local deployment by following these steps:
Creating app.py
To create the app.py
file, follow these steps
- Copy all the code from the final cell in the Jupyter Notebook and paste it into a new Python file named
app.py
. - Remove notebook-specific dependencies. Anything related to
nest_asyncio
is no longer needed, it is only necessary in Jupyter notebooks. Additionally, remove theuvicorn.run(...)
call, as the server will be launched outsideapp.py
.
Creating requirements.txt
For out simple project, you could easily create the requirements.txt
file manually, but I am too lazy for that, so I am using the pipreqs
package to generate it for me
If you don’t have the pipreqs
package installed, you can simply install it using pip:
pip install pipreqs
Now you can generate the requirements.txt
. Either cd
into the directory where your app.py
file is located and run
pipreqs .
Alternatively, you can specify the path to the app.py
file
pipreqs path/to/app.py
Installing Dependencies
Once you have the requirements.txt
file, you can install the dependencies using pip
pip install -r requirements.txt
When you are developing your own app, and you started in a Jupyter notebook, the installation of the dependencies is a self-fulfilling prophecy, but once we move to a virtual environment, you need to install the dependencies.
Running the App
Now you can run your app with Uvicorn from the terminal. From the directory where app.py
is located, start the API server with:
uvicorn app:app --reload
Let’s break down the command:
uvicorn
: The Uvicorn server.app:app
: This follows the format: : It tells Uvicorn to look for the FastAPI app instance named app
inside the Python moduleapp.py
. Since both arguments are the same, let’s change it for clarity. If you had writtengreeting_app = FastAPI()
inside a file calledapi_app.py
, you would runuvicorn api_app:greeting_app --reload
--reload
: Automatically restarts the server whenever you make code changes — useful during development.
Running the App in a Virtual Environment
So far, we have re-created the behavior of the Jupyter Notebook in a Python file. However, when we deploy the app in the cloud, we will have a different environment. To make sure that we defined the dependencies correctly and the app runs as expected, we should test it in a virtual environment.
Creating a Virtual Environment
To create a virtual environment, you can use the venv
module that comes with Python. Open your terminal and navigate to the directory where your app.py
file is located. Then, run the following command to create a virtual environment named venv
:
python -m venv venv
Let’s break down the command:
python
: The Python interpreter.-m venv
: Thevenv
module, which is used to create virtual environments.venv
: The name of the virtual environment.
Activating the Virtual Environment
Once the virtual environment is created, you need to activate it. The activation command depends on your operating system:
- Windows:
venv\Scripts\activate
- macOS/Linux:
source venv/bin/activate
As a result, you should see the name of the virtual environment (venv
) as a prefix in your terminal.
Installing Dependencies
Now that you have activated the virtual environment, you can install the dependencies using pip. From the directory where app.py
is located, run:
pip install -r requirements.txt
Now the virtual environment has all the dependencies from requirements.txt
installed, simulating the environment in which the app will be deployed in the cloud.
Running the App
Now you can run your app with Uvicorn from the terminal. From the directory where app.py
is located, start the API server with:
uvicorn app:app --reload
Deactivating the Virtual Environment
When you are done testing, you can deactivate the virtual environment by running:
deactivate
Deploying the API in the Cloud
After we have successfully tested our API locally, it is time deploy it in the cloud. I will use Render to deploy my API, because they have a free tier that allows me to deploy the API for free.
To clearly separate the local development from the cloud deployment, I created a new folder called app-render
and copied the app.py
and the requirements.txt
file into it.
After uploading everything to my GitHub repository, I created a new service in Render and linked it to my GitHub repository. During service creation, set the following parameters:
- Service Type:
Web Service
- Language:
Python 3
- Branch:
main
- Root Directory:
app-render
- Build Command:
pip install -r requirements.txt
- Start Command:
uvicorn app:app --host 0.0.0.0 --port $PORT
- Instance Type:
Free
After deployment, this is the URL of the API: https://fastapi-greeting-api.onrender.com
You can now call the API using the client notebooks for the POST method and the GET method
Conclusion
Taking the API from a Jupyter Notebook (my preferred environment for rapid prototyping) to a working cloud deployment took a few steps. First, we refactored the code into a standalone Python file (app.py
). Then we created a requirements.txt
file and tested everything locally in a clean virtual environment. Finally, we deployed the API to the cloud using Render. While the deployment step will vary across cloud providers, the general process is similar.
After building the greeting API in my previous blog post, we’ve now taken it all the way to the cloud. The goal here wasn’t to explore every FastAPI feature or every cloud deployment nuance, but to provide a reusable, step-by-step template for future projects and hackathons.
There’s lots more you could do, e.g. adding authentication, rate limiting, or monitoring, but we’ll leave that for another time. I Hope this was helpful, and happy coding!