Easily Deploy Simple Flask Apps to Heroku

Have a working Flask app you want to deploy to Heroku? Read on to learn how…

Flask and Heroku logos with a gradient between them

A few weeks ago I had a couple of Flask apps that I wanted to deploy to Heroku. My apps ran fine locally so I expected the process to be quite simple with Heroku’s ability to deploy directly from a GitHub repository. While I eventually got both of my apps up and running, I thought the resources I found were a bit too dense for the relatively straightforward process I used to get everything set up. I’m hoping this blog post helps someone in a similar position get their work deployed more quickly than I did. You can follow along as I explain each step or just scroll down for the abridged version at the bottom of this post.

1. Push Your App to a GitHub Repository

This step isn’t completely necessary since you can deploy using a combination of Git and the Heroku CLI, but I would definitely recommend just linking a GitHub repo because it’s much easier. If you aren’t sure how to get your local files into a GitHub repo, check out this guide by Karl Broman. Once you have your app in its own GitHub repository and you’ve confirmed that it runs locally you should be ready for the next step.

2. Set Up a Virtual Environment

Before we start creating the files Heroku needs to properly deploy your app we’re going to set up a virtual environment for your app. You don’t actually have to follow this step but I highly recommend doing it to avoid the messy alternative. That said, if you don’t want to use a virtual environment, feel free to skip ahead to section 3.

So why a virtual environment?

  • A virtual environment allows you to keep specific versions of libraries installed for app development and testing while still allowing you to update everything to the newest version outside of that environment. This is especially handy if you’re using a package management system like Conda that encourages you to update all packages simultaneously.
  • Having a virtual environment for your app makes it easy to get a list of the packages it requires to run, which is exactly what we’ll do in the next step.

Follow this guide from Real Python to set up your virtual environment and make sure it’s running for the remaining steps. If you try to run your app it should fail because your newly-created virtual environment doesn’t have Flask or any of the other Python libraries your app is using installed yet.

ModuleNotFoundError: No module named 'flask'

So in order to make your app functional again, you’ll have to install all necessary packages in the virtual environment using pip. For Flask the shell command looks like this:

(env) $ pip install flask

Once you can launch your app locally from the virtual environment you should be ready for the next step.

3. Install and Test Gunicorn

Regardless of whether or not you created a virtual environment, you’ll need to use Gunicorn to get your app to run properly on Heroku. Flask’s built-in web server cannot handle concurrent requests, but Gunicorn can. For a much better, in-depth explanation check out this Heroku article. What you want to do now is install Gunicorn and make sure you can run your app with it. Let’s first install it:

(env) $ pip install gunicorn

And now navigate to the directory containing your Flask app and let’s make sure it works with Gunicorn. The command below will run the function app from the file app.py contained in the current working directory using Gunicorn. You may need to change the command slightly based on what you named things; just follow this format: gunicorn (your file):(your function).

(env) $ gunicorn app:app

You should see a message telling you that Gunicorn is running and a local address you can open in a web browser. All app functionality should be the same as if you ran it through Flask’s built-in web server.

If your Flask app script is not in the root directory of your GitHub repository, you’ll also want to test a modified version of this command. We’ll be telling Heroku to use Gunicorn to run your app, but it does that from the root directory. So let’s navigate to the repo root directory and test Gunicorn again (if your app script is in the root directory you can just skip this part). The command below uses the –pythonpath flag so Gunicorn can find my app file in a subdirectory. Follow this format for your own file hierarchy: gunicorn –pythonpath (app directory) (your file):(your function).

(env) $ gunicorn --pythonpath flask app:app

If everything works properly, you’re ready to create the three files Heroku needs!

4. Add ‘Procfile’ to Your Repository

The Procfile is what Heroku uses to launch your app and should be easy to create because we just figured out what needs to be in it in the last step. All you have to do now is put web: in front of the Gunicorn command you ran from the root directory of your repository and save that in a plain text file called Procfile in your repo root. My Procfile looks like this:

web: gunicorn --pythonpath flask app:app

That’s it. Just follow the pattern web: gunicorn –pythonpath (app directory) (your file):(your function) and save it in Procfile.

5. Add ‘runtime.txt’ to Your Repository

Next we’ll create runtime.txt, which tells Heroku what version of Python you want to use to run your app. You can get your Python version through the command line by running this line:

(env) $ Python -V

You should see output that looks something like this:

Python 3.7.3

Now all you have to do is properly format the Python version and save it in a plain text file called runtime.txt in the root directory of the repo. For the version above the file contents should look like this:

python-3.7.3

Before deploying you should also check the Heroku Dev Center to confirm that you’re specifying a supported version of Python.

6. Add ‘requirements.txt’ to Your Repository

The last file we need to create is requirements.txt, which tells Heroku exactly what Python libraries your app is dependent upon. Did you set up that virtual environment in Step 2? If you did, congratulations, this step is going to be really simple. Make sure your virtual environment is still activated and run the command below to write a list of the libraries your code needs to run into requirements.txt.

(env) $ pip freeze > requirements.txt

You can also run pip freeze by itself to get the list of libraries without creating the requirements.txt file. If you set up a virtual environment, the list should be pretty short because that environment contains only the libraries your app needs to run. If you didn’t use a virtual environment your list will contain every Python library pip has installed on your machine, which is likely way more than you need just to run your app. You can whittle down that list by manually deleting items from requirements.txt, but that is definitely not a best practice. It’ll work, but I highly recommend using a virtual environment instead.

7. Push Your New Files to GitHub

Once you have Procfile, runtime.txt, and requirements.txt saved locally in your app’s root directory you’ll want to commit and push them to your GitHub repository. Since you’ll be connecting the GitHub repo for the app to Heroku for deployment, all necessary files need to be in your online repository.

8. Connect Your GitHub Repo to a Heroku Project

You’ll need to first create a Heroku account if you don’t already have one and then create a new app through the Heroku web interface. I won’t detail how to do either of those things here because Heroku’s interface makes it very simple. Once you’ve created your app you should see a section called Deployment Method under the Deploy tab: Click Connect to GitHub.

Screenshot of Deployment Method Menu

Once you give Heroku permission to access your GitHub account you’ll be able to search for your app repository and then connect to it.

Screenshot of GitHub connection interface

9. Deploy Your App

With your repository connected you should now be able to deploy it under the Manual Deploy section. Just select what branch you want to use and click Deploy Branch. There’s also an option for automatic deployment which will deploy a new version of your app on Heroku every time you push to the deployed branch on GitHub.

Screenshot of Manual Deploy interface

You can check the results of your build under the Activity tab: if everything worked you should see Build succeeded after your latest build attempt. If you see Build failed check the build log to see what went wrong. I’ve found googling the exact error message from the logs to be very helpful when I’m not sure how to fix a failed build.

Screenshot of Activity Feed

You may also run into a situation where your build succeeds but does not run properly or at all. Because the build was successful, you won’t find any error messages in the build log and will instead have to view the Application Logs. Click the More dropdown menu in the upper right corner of the Heroku dashboard and select View Logs to access them.

Screenshot of Activity Logs button

Googling error messages will again come in handy when troubleshooting activity logs. I was having trouble getting an app that uses OpenCV to run despite a successful build and was able to quickly resolve my problem thanks to a search turning up this StackOverflow thread.

Thanks for Reading!

Hopefully you’ve now successfully deployed your Flask app to Heroku. If it didn’t work for you, please let me know what or where things went wrong so I can make improvements to this post. If you want to dig deeper into Heroku, a good place to start is the well-organized Heroku Dev Center. Thanks for reading and happy Heroku deploying!


TL;DR

Here’s how to deploy a Flask app on Heroku:

  1. Push your working Flask app to a GitHub repository
  2. Set up a virtual environment and install all library dependencies
  3. Install and test Gunicorn locally
    gunicorn --pythonpath (app directory) (file name):(function name)
  4. Add ‘Procfile’
    web: gunicorn --pythonpath (app directory) (file name):(function name)
  5. Add ‘runtime.txt’
    Python -V
  6. Add ‘requirements.txt’
    pip freeze > requirements.txt
  7. Push new files to the GitHub repository
  8. Connect GitHub repository to Heroku and deploy
  9. Deploy your app

Data Science Bootcamp Applications

This is the first post in a series on my experiences attending the Metis immersive Data Science course in New York City. My subsequent posts cover pre-bootcamp and Week 1 and Weeks 2-12. While I cannot guarantee anyone else’s bootcamp will be the same as mine, I hope you find these posts as useful as I found other blogs when I was researching data science programs.


I distinctly remember that filling out my first bootcamp application was the moment in my journey towards data science that I thought, this is really happening. Although I had been planning to leave my job for a little while and had been learning some data science fundamentals through MOOCs beforehand, applying felt like my first serious step in changing careers. In determining to which immersive programs I wanted to apply, I found the personal testimonials of blogs to be among the most helpful resources, more candid than program sales pitches and far more in-depth than most reviews on SwitchUp and Course Report. Given what a gigantic leap applying felt like to me I am a bit surprised I did not find more posts about the admissions process, and that is what motivated me to write about my experience.

For the sake of brevity I won’t delve much into the details of test questions, interviews, or programming challenges, especially since most of that information is readily available online. If a particular data science program doesn’t describe their admissions process on their website you should be able to get a full rundown of entrance requirements by emailing them. I will also add the caveat that my admissions experiences are limited to just two in-person, immersive programs in New York City, Galvanize and Metis, which represent only a fraction of the full breadth of data science classes. I won’t get into why I picked Metis here, but will likely write about my decision in a future post. While I researched as many options as I could find, I eventually settled on applying to two schools, a limit I recommend not exceeding if you will be applying simultaneously and are working full-time. Data science bootcamps generally have a limited number of spots per session and use the admissions process to find the most suitable candidates. It’s important to know that programs vary significantly in the difficulty and length of their admissions processes; some programs only require a couple of online interviews while others, like Galvanize and Metis, employ far more extensive screening.

Initial applications tend to be fairly uniform, consisting of an online form asking who you are, where you’re from, why you want to study data science, and when you want to start, all (hopefully) easy questions that shouldn’t require more than an hour or two to answer. Submitting an application puts into motion a time-sensitive process that involves completing programming challenges, taking timed online quizzes, and interviewing with school staff through video chat. While you may have some flexibility in scheduling when you undertake these tests, you probably won’t have the time to familiarize yourself with a topic that is completely new to you. Fortunately, schools will usually tell you exactly what they want you to know before you apply and some, like Metis, even have practice assessments you can use to gauge your readiness for admissions. I highly recommend studying topics like linear algebra, calculus, statistics, and scripting (generally coding challenges are in Python) and evaluating your progress with practice quizzes before you apply. Thanks to my preparation, I found both the Galvanize and Metis admissions tests to be challenging but well within my understanding of the material. While I had plenty of prior experience with Python, I had not studied any of the math topics in many years and would have fared far worse on those sections had I not spent a considerable amount of time reacquainting myself with them. If you also feel the need to review the math or statistics fundamentals, I recommend the sites Math is Fun and Mathopolis, which work in tandem to provide simple lessons and corresponding challenges to test your knowledge. For a more advanced understanding of math topics, check out 3Blue1Brown on YouTube, which includes entire series on linear algebra and calculus. A great book for beginners to coding is Learn Python the Hard Way, which should more than prepare you for admissions coding challenges. I utilized all of these resources and found them to be extremely helpful, but by no means is the list exhaustive.

Even though I felt prepared for admissions, I was surprised by the speed and intensity of the whole process. While I was successful in finishing the bulk of both applications on weeknights after work, in retrospect, waiting for the weekend would have been a smarter approach. Trying to complete a 48-hour coding challenge in the free time a full-time job affords is certainly not impossible, but it can add a good deal of unnecessary stress. Saving assessments for the weekend would have allowed more uninterrupted work time and fewer lost hours of sleep. For both Galvanize and Metis, successfully negotiating the online tests and coding challenges ushers in the final round of admissions testing: one or more online interviews with data scientists affiliated with the school. The interviewers are there to serve as a hybrid of test administrator and benevolent guide if you get stuck. I found the interviews to be friendly and casual, but simultaneously nerve-wracking, and recommend studying any suggested materials and more beforehand, particularly if you don’t like being asked to solve problems on the spot. I spent an estimated ten hours working through each program’s admission process from start to finish, not counting time spent studying.

Once you complete all phases of the application process you may have to wait up to a week to hear back from the school’s admissions office with your results. If you are admitted you’ll have to sign an agreement and make a deposit, usually within a week, in order to secure your seat in a cohort. I paid my deposit a little less than four weeks after filling out my first application, but that timeline could certainly have been made shorter if I hadn’t been simulatenously navigating two admissions processes. An advantage to applying to multiple schools at the same time is that if you get admitted to more than one you’ll have the luxury of being able to pick whichever you think is best. Alternatively, if you apply early enough and don’t get into your first choice of program you can try to get into a different school that has a cohort starting around the same time. I have also heard from admissions officers at various schools that early applicants have a better chance of being accepted due to class sessions having more open spots and fewer candidates farther out from their start dates. Some programs require several hours of work to be completed before the first day of class, and early admission affords you a head start on any pre-bootcamp assignments or extra studying you might want to undertake.

Hopefully this post sheds some light on the data science bootcamp admissions process and gives you an idea of what to expect if you decide to apply to one. If you want more details or have any other questions, feel free to email me at [ lukaswadya@gmail.com ]. Thanks for reading!


TL;DR

  • Admissions can take a while, consider limiting your number of applications if you’re working full-time
  • Study before applying because you may not have enough time to do so once you start the process
  • Applying early gives you more flexibility and may make getting admitted to a competitive program easier