Run Sanic on Heroku
Posted on Thu 19 May 2022 in Technical Solutions
Updated on Tue 30 Aug 2022
Introduction¶
Recently I needed to set up a very simple proof of concept (POC) to demonstrate to myself and eventually my team that an idea would work. A POC isn't production ready, it doesn't need to be robust and in my case wasn't even going to be written using the same framework we use in production. I just needed to see if the integration would work as I thought it would. If it did, I'd work with my team to build a production ready version. If it didn't work, no problem. I expected this POC to take about two hours of my time, including initial research around the integration itself.
My background is utilizing Python. I've been using it for nearly 15 years now. In my previous role I utilized Sanic to build our API. I've also used Django and Flask in the path, but it had been five or more years so I was rusty in those. Plus, I have a fancy new book written by Adam Hopkins, the core developer of Sanic and an amazing former colleague, called Python Web Development with Sanic that I wanted to work through. I've been meaning to get to this, and haven't had a lot of time with my recent job change. This small POC won't get far, but I've found that if I start following a long tutorial or course or book, I'll dedicate more time so that I can finish it.
By the way, I highly recommend the book if you are utilizing Sanic.
Onward!
IMPORTANT UPDATE: This post was written and utilized a free Heroku Dyno. On August 25, 2022, it was announced that the free tier would be going away on November 28, 2022. All of this will continue to work, but you won't be able to utilize the free tier to try it out after that date.
Problem¶
The problem I encounted during this POC wasn't the integration, like I expected. Instead, the problem I ran into was figuring out where I could deploy this POC at no cost. I considered ngrok, but that meant leaving something running on my machine until my team had a chance to play with the POC. Instead, I turned to Heroku. The next problem I ran into was determining how to deploy a Sanic application to Heroku. Google returned 5 year old articles, forum posts that don't have answers (denvercoder9, is that you?), and Flask tutorials.
Toy Sanic App¶
Before I get to the solution, here is a toy Sanic app that simply prints Ok!
when you hit the root endpoint. Save this in a file called server.py
from sanic import Sanic
from sanic.response import text
import os
app = Sanic(__name__)
@app.get("/")
async def root_path(request):
return text("Ok!")
app.run(host="0.0.0.0", port=os.environ["PORT"], debug=True, access_log=False)
The one important thing to notice is that port
parameter in app.run()
. Heroku supplies the port it is listening on on an environment variable, and this is needed for Sanic.
The quick solution¶
In Adam's book, in the "Organizing a Project" chapter, he shows that running an application uses a command like:
sanic src.server:app -p 7777 --debug --workers=2
Simplifying that command a bit and setting up the Heroku Procfile
(capitization matters and no extension) I have a single line in my Procfile
that reads:
web: sanic server:app
Creating a requirements.txt
file with Sanic as an item was also required. If you're using a virtualenv, you can simply pip freeze > requirements.txt
to get everything in your environment into the file.
Thus, my directory looks like this:
./poc
Procfile
requirements.txt
server.py
Push this to Heroku and the application fires right up.
More details¶
I did not have a personal Heroku account or the CLI installed on my machine before starting. That was easily resolved by creating an account at Heroku. For the heroku-cli
, I followed the documentation to get that set up. Namely:
curl https://cli-assets.heroku.com/install.sh | sh
Note: This does require sudo
.
Once that's done, I verified the installation:
$ heroku --version
heroku/7.60.2 linux-x64 node-v14.19.0
Set up the new application in your Heroku account by logging in. Then click New
then Create new app
.
Enter a unique application name.
Then add Python to the build path. Do this by going to Settings
-> Add buildpack
-> Selecting Python and clicking save.
The next step is setting up the two files I mentioned earlier - Procfile
and requirements.txt
. Since the Procfile
is a single line for this simple proof of concept, that can been done in a single line from the shell.
$ echo "web: sanic server:app" > Procfile
Assuming you've been using a virtualenv - because you should be using a virtualenv - the requirements.txt
file is just as easy.
$ pip freeze > requirements.txt
Everything is setup and ready to be loaded to Heroku. Next, login in your terminal. I used the browser based method, but you can do this entirely in the command line if you wish. My command was:
heroku login
Last, I set up a heroku git remote endpoint so that I could push
heroku git:remote -a NAME_OF_YOUR_HEROKU_APP
git add .
git commit -m "Deployment commit"
git push heroku master
Change NAME_OF_YOUR_HEROKU_APP
to match the name you input in the UI when setting it up.
Wait a minute or so, and then navigate to NAME_OF_YOUR_HEROKU_APP.herokuapp.com
and see Ok!
Finishing up¶
With the steps above, I got a very simple Sanic proof of concept running on Heroku in a matter of minutes. This was very helpful as I was able to easily show my team that the work we're thinking of doing can be accomplished. All told, my proof of concept took two hours of time. The next step will be building a production version.