As part of a recent project demo, I wanted to use Pivotal CF / Pivotal Web Services to deploy and execute a python application. While there are other options on the market, they aren't Federation solutions, and so aren't preferable.
So what was the problem? Well, by default CF only supports Ruby, Java and Node.js applications. While those are all great languages, they aren't python, and so they aren't for me.
Specifically, I'm a fan of the Flask microframework for creating web apps, so I wanted to make that work in CloudFoundry.
Fortunately, CloudFoundry supports the concept of a 'buildpack', or a custom execution evironment. As a result, as long as it can run in Linux, you can probably get it to run on CloudFoundry.
The first task, was to write a very simple flask application:
import os import pprint import logging from flask import Flask app = Flask(__name__) logging.basicConfig(level=logging.DEBUG) @app.route('/') def hello(): return 'Hello World!\n' + pprint.pformat(str(os.environ)) port = os.getenv('VCAP_APP_PORT', '5000') if __name__ == "__main__": app.run(host='0.0.0.0', port=int(port))
This is the equivalent of "Hello World". The only 'strangeness' here is the following:
port = os.getenv('VCAP_APP_PORT', '5000')
which uses the VCAP environment variables that CF sets in order to listen on the correct port. If that value is not found, it defaults to 5000. Note that your application gets routed through some network address translation and load balancing when deployed to the cloud, so users still access it via port 80 - this is just internal housekeeping. Note that you'll need to install the flask module before this will work - using pip and virtualenv are probably the best route.
Now we want to deploy our application. First, sign up for a free Pivotal CF account at run.pivotal.io:
Then you can login to the console:
Overall thats pretty simple. The last thing we need to do is install the cf command line tools. They are pretty easy to install.
I then login and get a bit of feedback:
(cf-mcowger1)[mcowger@Vox] Projects/hello-python: → cf login -a https://api.run.pivotal.io ] API endpoint: https://api.run.pivotal.io Username> <redacted> Password> Authenticating... OK Targeted org mkc Targeted space development API endpoint: https://api.run.pivotal.io (API version: 2.2.0) User: <redacted> Org: mkc Space: development
The next step is to collect all the requirements into a file. pip makes this easy by enabling us to output a requirements.txt file in the correct format:
(cf-mcowger1)[mcowger@Vox] Projects/hello-python: → pip freeze > requirements.txt ] (cf-mcowger1)[mcowger@Vox] Projects/hello-python: → car requirements.txt ] zsh: command not found: car (cf-mcowger1)[mcowger@Vox] Projects/hello-python: → cat requirements.txt ] Flask==0.10.1 Jinja2==2.7.2 MarkupSafe==0.19 Werkzeug==0.9.4 itsdangerous==0.24 wsgiref==0.1.2
Lastly, we need to tell CF how to run this application (e.g. specify command lines, etc). This is done with a 'Procfile', and is quite simple:
→ cat Procfile ] web: python hello.py
The last step is to deploy, or 'push' the app to Pivotal CF. This is easily done with the following command
cf push mcowger-1 -b https://github.com/ephoning/heroku-buildpack-python -m 128m -i 1
Let's break that down:
- push: deploy a web application
- mcowger-1: what to call this web application. By default, this will also be in the URL (although it can be changed)
- -b https://github.com/ephoning/heroku-buildpack-python: Here we specify that custom buildpack I mentioned, using an opensource one from github. Fortunately, CloudFoundry can use most Heroku buildbacks (they use the same concept) with minimal, if any, modifications.
- -m 128m: How much memory to alllocate your application. A minimal application like this needs minimal memory
- -i 1: How many instances of this should we run. Its entirely possible to scale your application (assuming its designed for it) by changing this value.
Out of that, CF gives us a bunch of status output, and if all goes well, after minute or two, you'll get:
requested state: started instances: 1/1 usage: 128M x 1 instances urls: mcowger-1.cfapps.io
And would you look at that, you can hit mcowger-1.cfapps.io and see your application running live for the world. Now, your next application should be somewhat more complex, but you get the idea. As you add more modules, don't forget to use the 'pip freeze' command to add them to requirements.txt!
In a future post I'll discuss using marketplace apps to back your application with things like memcached, redis or PostgreSQL.