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:
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:
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:
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.
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 email@example.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!