Quick and Dirty Python
Deployments with Heroku
Guest starring Flask, CoffeeScript, Fabric, and
                  SeatGeek

                         Daniel Pritchett for MEMpy,
                                      March 19, 2012
Painless Heroku Startup
Requirements
•   Python 2.7
•   virtualenv
•   pip
•   Rubygems
•   Procfile / foreman
Get started
• Install git, foreman, pip, virtualenv
• Clone/create a repo with a Procfile that
  starts a HTTP service
• foreman start to test it locally
• heroku create app_name –
  stack=cedar && git push heroku
  master
Setup log
$ virtualenv --no-site-packages heroku_demo
   New python executable in heroku_demo/bin/python
   Installing pip...............cdone.
$ cd heroku_demo/
$ . bin/activate
$ git clone git://github.com/dpritchett/wwebsite-python.git app
$ cd app
$ pip install -r ./requirements.txt
   Successfully installed Flask Jinja2 Pygments Werkzeug chardet gunicorn
$ foreman start
   13:20:18 web.1     | started with pid 17810
   13:20:18 web.1     | 2012-03-19 13:20:18 [17810] [INFO] Starting gunicorn 0.14.1
   13:20:18 web.1     | 2012-03-19 13:20:18 [17810] [INFO] Listening at: http://0.0.0.0:5000
$ heroku create mempy-demo --stack=cedar
   Creating mempy-demo... done, stack is cedar
   http://mempy-demo.herokuapp.com/ | git@heroku.com:mempy-demo.git
   Git remote heroku added
$ git push heroku master
   Procfile declares types -> web
   http://mempy-demo.herokuapp.com deployed to Heroku
$ curl mempy-demo.herokuapp.com
   Hello World!
Foreman’s Procfile defines the service


web: gunicorn app:APP -b 0.0.0.0:$PORT -w 3

You can run the same thing at the console to test:
  $ gunicorn app:APP -b 0.0.0.0:$PORT -w 3
Heroku logging
• Captures stdout, stderr
• You’ll need it since you have no persistent disk
• Simplest case you can just use a print statement
• Free plan has limitations
• Consider an offsite log manager
Remote console
$ heroku run bash
    Running bash attached to terminal... up, run.2
~ $ find templates
    templates
    templates/index.html
~ $ find static
    static
    static/js
    static/js/memphis_tickets.js
    static/coffee
    static/coffee/memphis_tickets.coffee
    static/bootstrap
    static/bootstrap/js
    static/bootstrap/js/bootstrap.js
     ...
    static/bootstrap/css/bootstrap.css
    static/css
    static/css/tickets.css
~ $
Sample Flask application:
 TicketsOfMemphis.com
The entire backend
HTML templating (Jinja2)
CoffeeScript excerpts
Data provided by SeatGeek API
Honorable mention: Fabric
             $ fab s
               [localhost] local: coffee -o ../js/ --compile
             ./*coffee

               [localhost] local: foreman start
               14:11:29 web.1     | started with pid 24218
               14:11:29 web.1     | 2012-03-19 14:11:29
             [24218] [INFO] Starting gunicorn 0.14.1
               14:11:29 web.1     | 2012-03-19 14:11:29
             [24218] [INFO] Listening at: http://0.0.0.0:5000
             (24218)
               14:11:29 web.1     | 2012-03-19 14:11:29
             [24218] [INFO] Using worker: sync
                        14:11:29 web.1     | 2012-03-19
             14:11:29 [24225] [INFO] Booting worker with pid:
             24225
               14:11:29 web.1     | 2012-03-19 14:11:29
             [24226] [INFO] Booting worker with pid: 24226
               14:11:29 web.1     | 2012-03-19 14:11:29
             [24227] [INFO] Booting worker with pid: 24227
Heroku Ecosystem

Pain points and add-ons
addons.heroku.com
•   Databases
•   Worker hours
•   Email services
•   DNS
•   HTTPS and certificates
•   Billing
•   Message/Task Queues
LogEntries
LogEntries Alerts
Zerigo DNS
MongoHQ
Thank you!
Try a copy of the code at
  github.com/dpritchett/wwebsite-python

Heroku and Flask have great docs.



Find me @dpritchett

Quick and Dirty Python Deployments with Heroku

  • 1.
    Quick and DirtyPython Deployments with Heroku Guest starring Flask, CoffeeScript, Fabric, and SeatGeek Daniel Pritchett for MEMpy, March 19, 2012
  • 2.
  • 3.
    Requirements • Python 2.7 • virtualenv • pip • Rubygems • Procfile / foreman
  • 4.
    Get started • Installgit, foreman, pip, virtualenv • Clone/create a repo with a Procfile that starts a HTTP service • foreman start to test it locally • heroku create app_name – stack=cedar && git push heroku master
  • 5.
    Setup log $ virtualenv--no-site-packages heroku_demo New python executable in heroku_demo/bin/python Installing pip...............cdone. $ cd heroku_demo/ $ . bin/activate $ git clone git://github.com/dpritchett/wwebsite-python.git app $ cd app $ pip install -r ./requirements.txt Successfully installed Flask Jinja2 Pygments Werkzeug chardet gunicorn $ foreman start 13:20:18 web.1 | started with pid 17810 13:20:18 web.1 | 2012-03-19 13:20:18 [17810] [INFO] Starting gunicorn 0.14.1 13:20:18 web.1 | 2012-03-19 13:20:18 [17810] [INFO] Listening at: http://0.0.0.0:5000 $ heroku create mempy-demo --stack=cedar Creating mempy-demo... done, stack is cedar http://mempy-demo.herokuapp.com/ | git@heroku.com:mempy-demo.git Git remote heroku added $ git push heroku master Procfile declares types -> web http://mempy-demo.herokuapp.com deployed to Heroku $ curl mempy-demo.herokuapp.com Hello World!
  • 6.
    Foreman’s Procfile definesthe service web: gunicorn app:APP -b 0.0.0.0:$PORT -w 3 You can run the same thing at the console to test: $ gunicorn app:APP -b 0.0.0.0:$PORT -w 3
  • 7.
    Heroku logging • Capturesstdout, stderr • You’ll need it since you have no persistent disk • Simplest case you can just use a print statement • Free plan has limitations • Consider an offsite log manager
  • 8.
    Remote console $ herokurun bash Running bash attached to terminal... up, run.2 ~ $ find templates templates templates/index.html ~ $ find static static static/js static/js/memphis_tickets.js static/coffee static/coffee/memphis_tickets.coffee static/bootstrap static/bootstrap/js static/bootstrap/js/bootstrap.js ... static/bootstrap/css/bootstrap.css static/css static/css/tickets.css ~ $
  • 9.
    Sample Flask application: TicketsOfMemphis.com
  • 11.
  • 12.
  • 13.
  • 14.
    Data provided bySeatGeek API
  • 15.
    Honorable mention: Fabric $ fab s [localhost] local: coffee -o ../js/ --compile ./*coffee [localhost] local: foreman start 14:11:29 web.1 | started with pid 24218 14:11:29 web.1 | 2012-03-19 14:11:29 [24218] [INFO] Starting gunicorn 0.14.1 14:11:29 web.1 | 2012-03-19 14:11:29 [24218] [INFO] Listening at: http://0.0.0.0:5000 (24218) 14:11:29 web.1 | 2012-03-19 14:11:29 [24218] [INFO] Using worker: sync 14:11:29 web.1 | 2012-03-19 14:11:29 [24225] [INFO] Booting worker with pid: 24225 14:11:29 web.1 | 2012-03-19 14:11:29 [24226] [INFO] Booting worker with pid: 24226 14:11:29 web.1 | 2012-03-19 14:11:29 [24227] [INFO] Booting worker with pid: 24227
  • 16.
  • 17.
    addons.heroku.com • Databases • Worker hours • Email services • DNS • HTTPS and certificates • Billing • Message/Task Queues
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
    Thank you! Try acopy of the code at github.com/dpritchett/wwebsite-python Heroku and Flask have great docs. Find me @dpritchett