Posted by virantha on Thu 14 November 2013

Starting a simple Flask app with Heroku

Flask and Heroku

Inspired by this article on Python Weekly, I thought I'd look into deploying a simple hello world application to Heroku, built on the Flask micro framework.

Here's my workflow:

  • Create a new directory and Python virtualenv (make sure virtualenvwrapper is installed!):

    cd ~/dev
    mkdir proj
    cd proj
    mkvirtualenv proj
    
  • At this point, I usually edit my virtualenv proj/bin/postactivate script to cd into proj, since I usually have multiple projects going on at the same time.

    #!/bin/tcsh
    # This hook is run after this virtualenv is activated.
    cd ~/dev/proj
    
  • Next, install the dependencies:

    1. pip install flask
    2. Get a Heroku account
    3. Install the Heroku tools. This gives you the command-line `heroku` tool to deploy and run your web app
  • Create the following hello.py web server:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    import os
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route("/")
    def hello():
        return "Hello world!"
    
    if __name__ == "__main__":
        port = int(os.environ.get("PORT", 5000))
        app.run(host='0.0.0.0', port=port)
    

    Line 11 where we define `port` is very important for running on Heroku. The default port of 5000 that a Flask app starts on does not work for a Heroku deployment. Instead, you need to get the PORT environment variable (that is set in each Heroku deployment environment, or dyno) and start the app listening on that port. For running locally for testing, if there is no PORT variable, then we use 5000

  • Test your Flask install by running this webserver:

    python hello.py
    

    You should see this in your terminal:

    * Running on http://0.0.0.0:5000/
    

    Now, navigate to localhost:5000 in your browser and make sure you can see "hello world" printed out in the browser window.

  • Files needed to deploy to Heroku: Now we're going to add some files that are required to help Heroku deploy your Flask powered web-app to its system:

    1. Python requirements file: Run the following to output a list of all your installed python packages

      pip freeze >! requirements.txt
      

      This should generate a file like the following (note, if you did not have a clean python package installation environment, you may have more packages listed below):

      Flask==0.10.1
      Jinja2==2.7.1
      MarkupSafe==0.18
      Werkzeug==0.9.4
      itsdangerous==0.23
      wsgiref==0.1.2
      

      Although it's usually good practice to change the `==` to `>=`, so that you're not tied to one particular version of a package, we'll leave this file as it is now.

    2. Procfile file: This is required for Heroku to deploy your app. Use the following:

      web: python dealscraper/hello.py
      

      You can test this by running ``foreman web`` and making sure your web server starts up again.

  • Deploy to the cloud!: You can now deploy your webserver to Heroku and have it run by them. Use the following commands to setup the deployment for the first time:

    git init
    git add hello.py requirements.txt Procfile
    git commit -m "Initial commit"
    heroku create
    heroku apps:rename proj
    git push heroku master
    

    Note that when you run ``heroku create`` it gives your app a random name like "serene-meadow-3827", so we want to rename it to our project name. If all goes well, the first time you do the create, it will ask your for your Heroku login and password, and then when you go the git push, it should show something like the following:

    Counting objects: 7, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (3/3), done.
    Writing objects: 100% (4/4), 472 bytes | 0 bytes/s, done.
    Total 4 (delta 1), reused 0 (delta 0)
    
    -----> Python app detected
    -----> No runtime.txt provided; assuming python-2.7.4.
    -----> Using Python runtime (python-2.7.4)
    -----> Installing dependencies using Pip (1.3.1)
           Cleaning up...
    -----> Discovering process types
           Procfile declares types -> web
    
    -----> Compiled slug size: 28.4MB
    -----> Launching... done, v5
           http://proj.herokuapp.com deployed to Heroku
    
    To git@heroku.com:proj.git
       0ed96f3..dcd13ba  master -> master
    

    Whenever you want to deploy a change in your code, just do the ``git commit -m "Message"`` and ``git push heroku master`` to push your changes to the Heroku infrastructure and restart your server.

  • Now, run heroku ps:scale web=1 to set your server to use one dyno or instance. You can check the status of your instance by doing heroku ps which should yield

    Scaling web dynos... done, now running 1
    

    Check that your process is running by doing ``heroku ps`` which might yield something like:

    === web (1X): `python hello.py`
    web.1: up 2013/11/14 15:58:28 (~ 22s ago)
    

    You can check the server logs by doing ``heroku logs``

  • Test the server: Just go to http://proj.herokuapp.com to see your web server in action!

© Virantha Ekanayake. Built using Pelican. Modified svbhack theme, based on theme by Carey Metcalfe