This tutorial assumes you’re deploying an existing app to Heroku, developed using Flask and Python 3 with no database
Deployment is complicated and requires knowledge of a lot of moving parts. Unfortunately, there often is no one-size-fits-all step-by-step tutorial to deploy a given app. Throughout this article, I’ve linked to important background information that may help you debug if things go wrong.
I’ve worked with a lot of students to get Flask projects deployed to Heroku, so I’m quite familiar with the edge cases and things you may forget while doing this. Commonly missed steps have been included as Notes, so pay close attention to them!
This tutorial assumes you’re deploying an existing app to Heroku, developed using Flask and Python 3 with no database. If your app does use a database, this tutorial will probably help with the non-db parts. If you’re using Postgres, read the Heroku guide on the topic.Heroku Postgres
Heroku Postgres is a managed SQL database service provided directly by Heroku. You can access a Heroku Postgres…devcenter.heroku.com
Flask
Virtualenv
If you aren’t already developing your app in a virtualenv
, make one now (otherwise skip to the next section):
In your project directory, run:
$ virtualenv -p python3 env
Then, activate it:
$ source env/bin/activate
Note: If you close the shell/terminal window make sure to reactivate the virtualenv!
Check to make sure your virtualenv
and pip
are using Python 3:
$ pip --version && python --version
You shouldn’t see Python 2.7 anywhere. If you do, something is wonky with your virtualenv, and you need to fix it before moving on.
Run your app. You’ll probably get missing dependency errors, so you’ll need to pip install
those. For example:
$ pip install flask
If this is your first time using a virtualenv
, I’d highly recommend reading about them here.
Packages to install
You will need Gunicorn:
$ pip install gunicorn
Gunicorn is a WSGI HTTP server that’ll handle requests made to your app when it’s deployed. It’s what most folks use to deploy Python apps.
When you’re done, make sure you have pip installed all the correct dependencies with your virtualenv
active, and run:
$ touch requirements.txt
$ pip freeze > requirements.txt
This command will add all of your app’s dependencies to a file, which will tell Heroku what it needs to install. Double-check your new requirements.txt
file. Make sure Flask and Gunicorn are in there and that you didn’t accidentally pip freeze
your entire local Python environment (Heroku will be very displeased with you if you have).
Files for Heroku
Make the following files in the same directory as your main app:
Procfile
web: gunicorn -w 4 app_file:app_name
The Procfile is for Heroku specifically. Replace app_file
here with whatever your main app file is called. I usually just name mine app.py
, so app
works.
app_name
is what you named your Flask app, so if your app is in a file called salmon.py
with a line that looks like aardvark = Flask(__name__)
, then the last line would look like salmon:aardvark
.
However, you most likely have a file called app.py
with a line that looks like app = Flask(__name__)
. In that case, your Procfile should simply contain:
web: gunicorn -w 4 app:app
The -w 4
specifies that we want four worker threads. A Procfile can have a bunch of other settings, too, that you can read about here.
runtime.txt
python-3.6.6
Heroku needs to know which Python version to use. Unfortunately, it doesn’t support every version, so you usually should just use a supported one in development. How to do that is outside the scope of this tutorial, so we’re just going to pick a version. To find out which runtime you have locally, do python --version
. Then, check Heroku’s supported runtime, and pick whichever is closest to yours (but don’t use 2.7).
.gitignore
env*.pyc
Having a .gitignore
isn’t strictly required but comes highly recommended. If you don’t have one you’ll upload unnecessary stuff from your development environment.
Note: If you’re using SQLite in development, you’ll really want to add that file as well because Heroku doesn’t need it. Plus, having files in your production environment that you don’t need can cause weird bugs down the line.
Git
If you aren’t already using Git for version control, you’ll need to use it for deploying to Heroku (installation instructions).
$ git init
$ git add -A
$ git commit -m "deploying to heroku"
Heroku
Sign up for Heroku, and install the CLI if you haven’t already. Make sure you are in the top directory of the app you’re deploying, and run:
$ heroku login$ heroku create example-app-name
$ git push heroku master
It’s very likely these turned up some errors. If so, check the debugging tips at the bottom. Once you get this working, run:
$ heroku open
Hopefully, that worked, and you have your app deployed! Let me know in the comments what went wrong for you and how/if you fixed it.
Debugging Heroku
Make extra sure that your app is running locally before you tear your hair out getting it to work on Heroku.
The most common type of error message I get when I first deploy Python apps seems to be pip install
errors. They looks a little like this:
remote: Could not find a version that satisfies the requirement pkg-resources==0.0.0 (from -r/tmp/build_1b06c0323986c42337cfd16a42542c2a/requirements.txt (line 11)) (from versions: )
remote: No matching distribution found for pkg-resources==0.0.0 (from -r /tmp/build_1b06c0323986c42337cfd16a42542c2a/requirements.txt (line 11))
remote: ! Push rejected, failed to compile Python app.
If this happens, try editing the version number in your requirements.txt
file. The above error turned out to be a bug related to my operating system, so I just deleted pkg-resources==0.0.0
from requirements.txt
and tried again.
Note: Another really common (and difficult to diagnose!) error is where one of your modules/files/folders has thesame name as one of the modules Heroku is using. You can tell this is happening by following the traceback
. Try to find errors thrown by code you didn’t write because it tried to call code you did write. The fix for this is, unfortunately, to rename the folders/files that are conflicting.
If you’re deploying data science projects (like tweet generators, for example), you’ll likely see an error like this at some point:
Error R14 (Memory quota exceeded)
That means your app is using too much memory for Heroku, and you either need to optimize your code or up the amount of memory Heroku will let it use.
To see the most recent error messages:
heroku logs --tail
Heroku logs might look confusing, but look for those familiar Python tracebacks. Look for messages like Python can not find Flask
that might indicate something is wrong with your requirements.txt
.
You can also try turning it off and on again.
To restart your app:
heroku restart
I’ll update this post with more tips as I come up with them.
Photo by Sharon McCutcheon on Unsplash