Here are some of my experiences getting Django working on Bluemix. I got it working most of the way that is until you try to access the database. These instructions might be helpful to someone who is also getting started getting Django going on Bluemix. Leave some suggestions if you know how I might get around my problem at the end. This post assumes you know how to use Django. Django is a Web Application framework written in Python based on Model View Controller pattern. Having previously deployed an existing Django Application I built on Heroku, I thought I would try to port the application to Bluemix to see if it would work. I was surprised at how quickly I was able to move it to Bluemix. The reason is was able to port it was because I am not using any proprietary or unique services in the application that only existed on Heroku. I recommend that you read the “Getting Started with Django Tutorial” on Heroku. While many of the concepts apply the command are obviously different.
Bluemix provide some great boiler plates for the most common platform as a service stack and continues to add new ones everyday. Unfortunately none of those are for Python or for Django. You can however still run Python apps like I showed in my Hello World Python Bluemix post.
Python utilizes a utility called PIP to install modules for your application. You can install Django utilizing PIP.
Install pip
http://pypi.python.org/pypi/pip
Follow directions here:
https://pip.pypa.io/en/latest/installing.html
On Windows
$python get-pip.py
Determine your application requirements
Locally install python package requirements for your application.
$python pip install django
Locally install python package requirements using my requirements.txt file below.
$python pip install –r requirements.txt
Or get install requirements for your application.
$python pip freeze –r > requirements.txt
Here is the requirements.txt file for the Django application I deployed to Bluemix. It includes the module and version.
Django==1.6.2 amqp==1.4.5 anyjson==0.3.3 autoenv==1.0.0 billiard==3.3.0.17 celery==3.1.11 dj-database-url==0.3.0 dj-static==0.0.5 django-celery==3.1.10 django-pagination==1.0.7 django-registration==1.0 django-taggit==0.11.2 django-toolbelt==0.0.1 gunicorn==18.0 httplib2==0.8 kombu==3.0.15 oauth2==1.5.211 oauthlib==0.6.1 pika==0.9.13 psycopg2==2.5.2 pysolr==3.2.0 pystache==0.5.4 python-openid==2.2.5 python-social-auth==0.1.24 python-twitter==1.3.1 pytz==2014.3 requests==2.3.0 requests-oauthlib==0.4.0 simplejson==3.5.2 six==1.6.1 static==1.0.2
The bare minimum you need are:
- Django – To install Django
- dj-database-url – To read the environment variable with the database name host, port, user id and password
- gunicorn – A WSGI server o serve HTTP content including your Django application
- psycopg2 – To allow your Django application to make Python Database calls to your Postgres Database Community Edition service on Bluemix.
- dj-static – To serve static content
Start a Django app locally
Create an empty top-level directory for our project:
$ mkdir hellodjango && cd hellodjango $ django-admin.py startproject hellodjango . $ manage.py startapp hello
Create a Profile file
Use a Procfile, a text file in the root directory of your application, to explicitly declare what command should be executed to start the Bluemix Instannces. Start the Gunicorn with a few arguments.
Here is the Procfile that I used for my app. It should be called Procfile and live at the root directory of our project:
Procfile
web: gunicorn hellodjango.wsgi --workers 3
Django settings
Next, configure the application for the Bluemix environment, including PostgreSQL database. The dj-database-url module will parse the value of the DATABASE_URL environment variable and convert them to something Django can understand.
Make sure ‘dj-database-url’ is in your requirements file, then add the following to the bottom of your settings.py file:
settings.py
# Parse database configuration from $DATABASE_URL import dj_database_url DATABASES['default'] = dj_database_url.config() # Honor the 'X-Forwarded-Proto' header for request.is_secure() SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO','https') # Allow all host headers ALLOWED_HOSTS = ['*'] # Static asset configuration import os BASE_DIR = os.path.dirname(os.path.abspath(__file__)) STATIC_ROOT ='staticfiles' STATIC_URL ='/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), )
With these settings available, you can add the following code to wsgi.py to serve static files in production:
wsgi.py
fromdjango.core.wsgiimportget_wsgi_applicationfromdj_staticimportCling application = Cling(get_wsgi_application())
Set database URL environment variable.
You can see whether or not you are getting your Database settings picked up by looking at the settings on error page on Django.
DATABASES |
{'default': {'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'CONN_MAX_AGE': 0, 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'HOST': '192.155.243.12', 'NAME': 'd4f5c4d18346a40a7a043cc5985fc2466', 'OPTIONS': {}, 'PASSWORD': u'********************', 'PORT': 5433, 'TEST_CHARSET': None, 'TEST_COLLATION': None, 'TEST_MIRROR': None, 'TEST_NAME': None, 'TIME_ZONE': 'UTC', 'USER': 'ucba74fb890ea4d999c31a90dd2f84b03'}} |
If you haven’t run python manage.py syncdb you will likely get this error
ProgrammingError at /yourURLContext/ relation "django_session" does not existLINE 1: SELECT (1) AS "a" FROM "django_session" WHERE "django_sessio...
Run test locally
Simple if it doesn’t work locally don’t expect it to work on Bluemix. Look out for python packages you installed locally using exe. For example I wasn’t able to get LXML to install on Bluemix because of this reason.
Deploy to Bluemix
There are many buildpacks available out there. The challenge is finding one that works with Django and Bluemix. I was able to use the one below to get my Django application to deploy and run on Bluemix.
$cf push hellodjango -m 256M -b https://github.com/ephoning/heroku-buildpack-python.git
1. First create database service and push web app without the db setup command. It deploys successfully.
$cf push app_name -m 256M -b https://github.com/ephoning/heroku-buildpack-python.git
2. Interactively in the Bluemix Web UI bind your app to your DB Service.
3. Now restart the app with command to populate DB. Now that you have a connection to it. Instead stop the app and then redeploy using the cf push command and this time append the -c “setup_db.sh” option.
$cf push app_name -m 256M -b https://github.com/ephoning/heroku-buildpack-python.git -c "bash ./setup_db.sh"
Where setup_db.sh looks like:
#!/bin/bash echo "Trying----------------------------- to synch" python manage.py syncdb --noinput echo "Finish manage.py synchdb ----------------------------" echo "from django.contrib.auth.models import User; User.objects.create_superuser('carlos', 'carlos.ferreira@us.ibm.com', 'carlos')" | python manage.py shell echo "Finish creating super user ----------------------------"
4. Now restart the app with command to run.sh without create users cf push command and this time append the option:
$cf push app_name -m 256M -b https://github.com/ephoning/heroku-buildpack-python.git -c “bash ./run.sh"
Where run.sh looks like:
#!/bin/bash if [ -z "$VCAP_APP_PORT" ]; then SERVER_PORT=5000; else SERVER_PORT="$VCAP_APP_PORT"; fi echo port is------------------- $SERVER_PORT python manage.py syncdb --noinput
Troubleshooting
Review the logs
$cf logs hellodjango
The above steps worked. However I initially was unable to synch my postgres database with the tables required by Django. Here are some of the options I tried to do to be able to get my database populated for Django to work:
Tried invoking a custom script like was done in this example.
Tried passing in the syncdb command using the – c option as part of my push.
$cf push hellodjango -c “python manage.py syncdb”
Review your logs to ensure your environment variables are set properly
$ cf files hellodjango /logs/env.log
Gotcha’s
If you install the wrong Psycopg2 like I did you likely will want to uninstall it. Make sure you get the right 32 bit version for your Operating System. Here is how remove python packages that were installed with easy_install which is another install utility useful for installing Pip but also exe packages like the one for psycopg2.
To uninstall an .egg you need to rm -rf the egg (it might be a directory) and remove the matching line from site-packages/easy-install.pth
Thanks for reading an appreciate comments or suggestions on my final hurdle getting this to work with Postgres database.
After running with -c “bash ./setup_db.sh”
Instance is not starting
It’s a shame there’s no access to a terminal utility on Bluemix so far. This would be a lot easier.
I have a problem when I push with the -c “bash ./setup_db.sh” option. In the logs I get the following:
2015-03-19T15:34:21.03-0300 [STG/0] OUT Install Mercurial if it appears to be required.
2015-03-19T15:34:21.54-0300 [STG/0] OUT Cleaning up…
2015-03-19T15:34:21.73-0300 [STG/0] OUT Django collectstatic support.
2015-03-19T15:34:57.51-0300 [DEA/110] OUT Starting app instance (index 0) with guid 7599ddf9-a0d5-4088-8d36-371a44e3f8d9
2015-03-19T15:35:09.03-0300 [App/0] OUT Trying—————————– to synch
2015-03-19T15:35:09.24-0300 [App/0] OUT Finish manage.py synchdb —————————-
2015-03-19T15:35:09.53-0300 [DEA/110] ERR Instance (index 0) failed to start accepting connections
2015-03-19T15:36:21.29-0300 [App/0] ERR manage.py: error: no such option: –noinput
2015-03-19T15:36:21.32-0300 [App/0] OUT Finish manage.py synchdb —————————-
2015-03-19T15:37:48.09-0300 [App/0] ERR Unknown command: ‘shell\r’
I am using django 1.6.5 and python 3.4.0, the app seemed to work on my previous deploy, but of course there was no database. Any ideas?
Thanks
Hi Tomas, Thanks for the comment. We just introduced CLI support called Bluemix LiveSync. It allows you to get access into the command line within the app environment. I haven’t had much time to experiment with it. Today it only support NodeJS. I am advocating heavily to get this supported across all the runtime build packs especially Python to enable use with Django. https://www.ng.bluemix.net/docs/#manageapps/bluemixlive.html#bluemixlive Regarding your problem. it looks like it isn’t properly escaping out the -noinput parameters you are adding in on the command line. Give me some time to investigate
I put this starter template on GitHub to make it easier for you and others to quickly deploy a Python Django app to bluemix. Deploy your Django Python app in 2 min to #Bluemix using this starter template that uses the #DeployToBluemix Button http://goo.gl/pyDqYe Let me know how it goes.
Hi Carlos,
Picking up from your example I put together an application using Django / Celery / RabbitMQ & Loggly on Bluemix for my own work integrating Watson and Python.
I wanted to give back to the community like you have, so I’ve published an open example as well, would love your feedback: https://github.com/Chaffleson/blupy