24

I've built a webapp using django. In order to host it I'm trying to use openshift but am having difficulty in getting anything working. There seems to be a lack of step by steps for this. So far I have git working fine, the app works on the local dev environment and I've successfully created an app on openshift.

Following the URL on openshift once created I just get the standard page of "Welcome to your Openshift App".

I've followed this https://developers.openshift.com/en/python-getting-started.html#step1 to try changing the wsgi.py file. Changed it to hello world, pushed it and yet I still get the openshift default page.

Is there a good comprehensive resource anywhere for getting local Django apps up and running on Openshift? Most of what I can find on google are just example apps which aren't that useful as I already have mine built.

Oliver Burdekin
  • 1,098
  • 2
  • 17
  • 36

4 Answers4

42

Edit: Remember this is a platform-dependent answer and since the OpenShift platform serving Django may change, this answer could become invalid. As of Apr 1 2016, this answer remains valid at its whole extent.

Many times this happened to me and, since I had to mount at least 5 applications, I had to create my own lifecycle:

  1. Don't use the Django cartridge, but the python 2.7 cartridge. Using the Django cart. and trying to update the django version brings many headaches, not included if you do it from scratch.
  2. Clone your repository via git. You will get yourproject and...

    # git clone yourrepo@rhcloud.com:app.git yourproject <- replace it with your actual openshift repo address
    
    yourproject/
    +---wsgi.py
    +---setup.py
    *---.openshift/ (with its contents - I omit them now)
    
  3. Make a virtualenv for your brand-new repository cloned into your local machine. Activate it and install Django via pip and all the dependencies you would need (e.g. a new Pillow package, MySQL database package, ...). Create a django project there. Say, yourdjproject. Edit Create, alongside, a wsgi/static directory with an empty, dummy, file (e.g. .gitkeep - the name is just convention: you can use any name you want).

     #assuming you have virtualenv-wrapper installed and set-up
     mkvirtualenv myenvironment
     workon myenvironment
     pip install Django[==x.y[.z]] #select your version; optional.
     #creating the project inside the git repository
     cd path/to/yourproject/
     django-admin.py startproject yourjdproject .
     #creating dummy wsgi/static directory for collectstatic
     mkdir -p wsgi/static
     touch wsgi/static/.gitkeep
    
  4. Create a django app there. Say, yourapp. Include it in your project.

  5. You will have something like this (django 1.7):

    yourproject/
    +---wsgi/
    |   +---static/
    |       +---.gitkeep
    +---wsgi.py
    +---setup.py
    +---.openshift/ (with its contents - I omit them now)
    +---yourdjproject/
    |   +----__init__.py
    |   +----urls.py
    |   +----settings.py
    |   +----wsgi.py
    +---+yourapp/
        +----__init__.py
        +----models.py
        +----views.py
        +----tests.py
        +----migrations
             +---__init__.py
    
  6. Set up your django application as you'd always do (I will not detail it here). Remember to include all the dependencies you installed, in the setup.py file accordingly (This answer is not the place to describe WHY, but the setup.py is the package installer and openshift uses it to reinstall your app on each deploy, so keep it up to date with the dependencies).

  7. Create your migrations for your models.
  8. Edit the openshift-given WSGI script as follows. You will be including the django WSGI application AFTER including the virtualenv (openshift creates one for python cartridges), so the pythonpath will be properly set up.

    #!/usr/bin/python
    import os
    virtenv = os.environ['OPENSHIFT_PYTHON_DIR'] + '/virtenv/'
    virtualenv = os.path.join(virtenv, 'bin/activate_this.py')
    try:
        execfile(virtualenv, dict(__file__=virtualenv))
    except IOError:
        pass
    
    from yourdjproject.wsgi import application
    
  9. Edit the hooks in .openshift/action_hooks to automatically perform db sincronization and media management:

    build hook

    #!/bin/bash
    #this is .openshift/action/hooks/build
    #remember to make it +x so openshift can run it.
    if [ ! -d ${OPENSHIFT_DATA_DIR}media ]; then
        mkdir -p ${OPENSHIFT_DATA_DIR}media
    fi
    ln -snf ${OPENSHIFT_DATA_DIR}media $OPENSHIFT_REPO_DIR/wsgi/static/media
    
    ######################### end of file
    

    deploy hook

    #!/bin/bash
    #this one is the deploy hook .openshift/action_hooks/deploy
    source $OPENSHIFT_HOMEDIR/python/virtenv/bin/activate
    cd $OPENSHIFT_REPO_DIR
    echo "Executing 'python manage.py migrate'"
    python manage.py migrate
    echo "Executing 'python manage.py collectstatic --noinput'"
    python manage.py collectstatic --noinput
    
    ########################### end of file
    
  10. Now you have the wsgi ready, pointing to the django wsgi by import, and you have your scripts running. It is time to consider the locations for static and media files we used in such scripts. Edit your Django settings to tell where did you want such files:

    STATIC_URL = '/static/'
    MEDIA_URL = '/media/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'wsgi', 'static')
    MEDIA_ROOT = os.path.join(BASE_DIR, 'wsgi', 'static', 'media')
    STATICFILES_DIRS = (os.path.join(BASE_DIR, 'yourjdproject', 'static'),)
    TEMPLATE_DIRS = (os.path.join(BASE_DIR, 'yourjdproject', 'templates'),)
    
  11. Create a sample view, a sample model, a sample migration, and PUSH everything.

  12. Edit Remember to put the right settings to consider both environments so you can test and run in a local environment AND in openshift (usually, this would involve having a local_settings.py, optionally imported if the file exists, but I will omit that part and put everything in the same file). Please read this file conciously since things like yourlocaldbname are values you MUST set accordingly:

    """
    Django settings for yourdjproject project.
    
    For more information on this file, see
    https://docs.djangoproject.com/en/1.7/topics/settings/
    
    For the full list of settings and their values, see
    https://docs.djangoproject.com/en/1.7/ref/settings/
    """
    
    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    import os
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))
    
    ON_OPENSHIFT = False
    if 'OPENSHIFT_REPO_DIR' in os.environ:
        ON_OPENSHIFT = True
    
    
    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
    
    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = '60e32dn-za#y=x!551tditnset(o9b@2bkh1)b$hn&0$ec5-j7'
    
    # Application definition
    
    INSTALLED_APPS = (
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'yourapp',
        #more apps here
    )
    
    MIDDLEWARE_CLASSES = (
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
    )
    
    ROOT_URLCONF = 'yourdjproject.urls'
    
    WSGI_APPLICATION = 'yourdjproject.wsgi.application'
    
    # Database
    # https://docs.djangoproject.com/en/1.7/ref/settings/#databases
    
    if ON_OPENSHIFT:
        DEBUG = True
        TEMPLATE_DEBUG = False
        ALLOWED_HOSTS = ['*']
        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql',
                'NAME': 'youropenshiftgenerateddatabasename',
                'USER': os.getenv('OPENSHIFT_MYSQL_DB_USERNAME'),
                'PASSWORD': os.getenv('OPENSHIFT_MYSQL_DB_PASSWORD'),
                'HOST': os.getenv('OPENSHIFT_MYSQL_DB_HOST'),
                'PORT': os.getenv('OPENSHIFT_MYSQL_DB_PORT'),
                }
        }
    else:
        DEBUG = True
        TEMPLATE_DEBUG = True
        ALLOWED_HOSTS = []
        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql', #If you want to use MySQL
                'NAME': 'yourlocaldbname',
                'USER': 'yourlocalusername',
                'PASSWORD': 'yourlocaluserpassword',
                'HOST': 'yourlocaldbhost',
                'PORT': '3306', #this will be the case for MySQL
            }
        }
    
    # Internationalization
    # https://docs.djangoproject.com/en/1.7/topics/i18n/
    
    LANGUAGE_CODE = 'yr-LC'
    TIME_ZONE = 'Your/Timezone/Here'
    USE_I18N = True
    USE_L10N = True
    USE_TZ = True
    
    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/1.7/howto/static-files/
    
    STATIC_URL = '/static/'
    MEDIA_URL = '/media/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'wsgi', 'static')
    MEDIA_ROOT = os.path.join(BASE_DIR, 'wsgi', 'static', 'media')
    STATICFILES_DIRS = (os.path.join(BASE_DIR, 'yourdjproject', 'static'),)
    TEMPLATE_DIRS = (os.path.join(BASE_DIR, 'yourdjproject', 'templates'),)
    
  13. Git add, commit, push, enjoy.

    cd path/to/yourproject/
    git add .
    git commit -m "Your Message"
    git push origin master # THIS COMMAND WILL TAKE LONG
    # git enjoy
    
  14. Your sample Django app is almost ready to go! But if your application has external dependencies it will blow with no apparent reason. This is the reason I told you to develop a simple application. Now it is time to make your dependencies work.

    [untested!] You can edit the deploy hook and add a command after the command cd $OPENSHIFT_REPO_DIR, like this: pip install -r requirements.txt, assuming the requirements.txt file exists in your project. pip should exist in your virtualenv, but if it does not, you can see the next solution.

    Alternatively, the setup.py is an already-provided approach on OpenShift. What I did many times is -assuming the requirements.txt file exists- is:

    1. Open that file, read all its lines.
    2. For each line, if it has a #, remove the # and everything after.
    3. strip leading and trailing whitespaces.
    4. Discard empty lines, and have the result (i.e. remaining lines) as an array.
    5. That result must be assigned to the install_requires= keyword argument in the setup call in the setup.py file.

    I'm sorry I did not include this in the tutorial before! But you need to actually install Django in the server. Perhaps an obvious suggestion, and every Python developer could know that beforehand. But seizing this opportunity I remark: Include the appropriate Django dependency in the requirements.txt (or setup.py depending on whetheryou use or not a requirements.txt file), as you include any other dependency.

This should help you to mount a Django application, and took me a lot of time to standarize the process. Enjoy it and don't hesitate on contacting me via comment if something goes wrong

Edit (for those with the same problem who don't expect to find the answer in this post's comments): Remember that if you edit the build or deploy hook files under Windows and you push the files, they will fly to the server with 0644 permissions, since Windows does not support this permission scheme Unix has, and has no way to assign permissions since these files do not have any extension. You will notice this because your scripts will not be executed when deploying. So try to deploy those files only from Unix-based systems.

Edit 2: You can use git hooks (e.g. pre_commit) to set permissions for certain files, like pipeline scripts (build, deploy, ...). See the comments by @StijndeWitt and @OliverBurdekin in this answer, and also this question for more details.

Community
  • 1
  • 1
Luis Masuelli
  • 12,079
  • 10
  • 49
  • 87
  • thanks so much for this. Progress is being made. Changes to the openshift wsgi are showing up. However when I edit the wsgi in the root to include from yourdjproject.wsgi import application I'm getting a 500 internal server error. I think it might be a problem with the action_hook files. I created them as .bat files. Is that correct? – Oliver Burdekin Nov 12 '14 at 12:09
  • If you are trying to use BATch syntax, then I have serious doubts it will work. If, OTOH, you're using the file as I gave you (the exact content), then it won't matter the file extension (the shebang is still pointing to bash). BTW those hooks only run when you deploy the application. Have you created your project properly? this includes properly pointing the database. – Luis Masuelli Nov 12 '14 at 14:21
  • Thanks luis, I've applied the updates. Now I have got rid of the 500 error. However, it's just showing the page contained in the openshift wsgi file and not the front page of my app. I've double checked on the local machine and it's running fine still on there. – Oliver Burdekin Nov 12 '14 at 17:10
  • Did you replace the WSGI script with the one in step 8? You shouldn't see the default script anymore, since given the "application" script the apache gets, the urls are interpreted by such script (besides, the original wsgi script should not exist anymore) – Luis Masuelli Nov 12 '14 at 19:19
  • Luis! Success! Now I can see the content of my front page. I still need to wangle in the static and media files (not being picked up) and I think the database has failed to migrate but I'm getting there. Thank you so much. – Oliver Burdekin Nov 13 '14 at 10:38
  • If you created the `wsgi/static` directory with the .gitkeep file inside, then it should bring no issues at all. Check that, and also check SO (in openshift) settings and file permissions. Those issues are, fortunately, minor (remember to check whether the mysql backend is being used in Django settings, and the MySQL 5.5 cartridge is installed in your app). – Luis Masuelli Nov 13 '14 at 13:55
  • Static files are all fine. I still can't get the action_hooks to run though. I've manually added my database using phpmyadmin but I'll keep plugging away at the action_hooks and report back if I discover what's wrong with them. – Oliver Burdekin Nov 14 '14 at 12:48
  • If you cannot run the hooks, log into your application via SSH, move to app-root/repo/.openshift/action_hooks, and execute `./build`, `./deploy`. If you can't get them running, do a `chmod u+x *` there. This is mostly caused by you running Windows. If it is not the case, remember to change the permissions for those files in your local repo with the same chmod command, and commit them again (since you cannot do that in Windows, permissions for the comitted files become 644) – Luis Masuelli Nov 18 '14 at 14:47
  • By "running" I make emphasis on doing the commits/pushes. – Luis Masuelli Nov 18 '14 at 16:52
  • Luis, I can ssh into the app and execute the scripts from there. Why are they not running when I push? IS it windows problem? – Oliver Burdekin Nov 24 '14 at 13:45
  • 1
    Yes. Windows does not have a permission system, so when you push, files go with 644 as permission. So they don't have an execute flag and arent thus executed. Besides, "build" and "deploy" have no extension so they could never be hinted about having such flag or not. You have to manually change the flags after you push. – Luis Masuelli Nov 24 '14 at 14:57
  • Sorry, I'm missing something basic. When you say: "1. Don't use the Django cartridge, but the python 2.7 cartridge." and then "3. Create a django project there", where does the django software come from? After creating a new application with the python 2.7 cartridge, OS allows you to add additional cartridges (various DBs, Jenkins, Cron) but it doesn't offer the option to add a django cartridge on top of Python. Where does django come from in your workflow? – Dave Jul 07 '15 at 18:52
  • You are absolutely right: Since you have a plain Python 2.7 environment, you will need to install the whole dependencies, but this happen in your local machine! If you read the whole instructions, you will have to populate the requirements.txt file with the Django dependency. – Luis Masuelli Jul 08 '15 at 23:26
  • 1
    point 2. is still unclear. Please explain how to do it and where. (from the answer below, I think you mean `rhc git-clone mysite`) – Pynchia Sep 08 '15 at 12:05
  • 1
    the more I read points 2 and 3 the less I understand. You clone your project (existing and working django project) and then in step 3 you create another django project from scratch? – Pynchia Sep 08 '15 at 12:09
  • 1
    On the point of windows and permissions, I've discovered that you can set the action_hooks to run everytime you push. After git add --all changed permissions for action_hooks will be returned to 644. However, if you add a git hook in .git/hooks/pre-commit you can automate changing them to executable. For example in the .git/hooks/pre-commit this will update build permissions before pushing: #!/bin/sh git update-index --chmod=+x .openshift/action_hooks/build A windows specific problem but took me a while to work out. – Oliver Burdekin Sep 08 '15 at 13:39
  • @Pynchia: In the OpenShift side, there's no Django Project created by default. The reason is simple: I use Python 2.7 cartridge instead of Django cartridge, and so OpenShift only creates the respective wsgi.py script. It is up to you to create the Django project directory tree. – Luis Masuelli Dec 16 '15 at 16:37
  • @Pynchia I added instructions. I don't use rhc toolkit but just plain git commands. You can clone it as you want. – Luis Masuelli Dec 16 '15 at 16:41
  • @Pynchia in point 2, when you see the downloaded structure in your repo, there's no django project inside. It would, however, if using Django cartridges. At the time this comment is written, I don't know what's the status of Django cartridges, but anyway I discourage using them since they are always outdated WRT the currently stable Django version. – Luis Masuelli Dec 16 '15 at 16:44
  • 1
    point 9. python manage.py migrate will not work in build action hook for Postgres or MySQL databases, because DB is taken down during build and deploy. It should be rather placed in post_deploy hook – Ivan Jan 04 '16 at 09:24
  • Migrate never gave me problems with MySQL cartridges. Perhaps now they have changed it so it is taken down, but as the time I wrote the article, I was using it in production apps. I will add your notes. – Luis Masuelli Jan 04 '16 at 14:45
  • No. Wait. The migrations are done in the deploy hook (Two hook files are edited). – Luis Masuelli Jan 04 '16 at 14:47
  • I find this the best answer thus far, I got the majority of applications working using this method. The only issue I face is the Build / Deploy action hooks being on windows, hell to deal with. Also, it seems that it is ignoring any requirements for pip in setup.py and also in requirements.txt it just doesn't seem to install anything. – Llanilek Jun 11 '16 at 23:49
  • openshift does not work with pip AFAIK in the build/deploy hools. My suggestion: in the provided setup.py file (every openshift plain python app or even django app -which I disregard- has) assign `install_requires=` the contents of your requirements.txt file except for the comments. – Luis Masuelli Jun 12 '16 at 00:04
  • 1
    Just wanted to mention here that, although Windows does not know about permissions, Git does. This means that even on Windows, you can set the permission flags when comitting to Git and they will be reproduced correctly when being pushed to OpenShift. See e.g. this answer: http://stackoverflow.com/questions/21691202/how-to-create-file-execute-mode-permissions-in-git-on-windows – Stijn de Witt Jul 25 '16 at 17:44
7
1)  Step 1 install  Rubygems
Ubuntu - https://rubygems.org/pages/download
Windows - https://forwardhq.com/support/installing-ruby-windows
$ gem
or
C:\Windows\System32>gem
RubyGems is a sophisticated package manager for Ruby.  This is a
basic help message containing pointers to more information……..

2)  Step 2:
$ gem install rhc
Or
C:\Windows\System32> gem install rhc

3)  $ rhc
Or
C:\Windows\System32> rhc

Usage: rhc [--help] [--version] [--debug] <command> [<args>]
Command line interface for OpenShift.

4)  $ rhc app create -a mysite -t python-2.7
Or 
C:\Windows\System32>  rhc app create -a mysite -t python-2.7
# Here mysite would be the sitename of your choice
#It will ask you to enter your openshift account id and password

Login to openshift.redhat.com: Enter your openshift id here
Password : **********


Application Options
---------------------
Domain:    mytutorials
Cartridges: python-2.7
Gear Size:  Default
Scaling:    no

......
......

Your application 'mysite' is now available.

 URL : http://mysite.....................
 SSH to :  39394949......................
 Git remote: ssh://......................

Run 'rhc show-app mysite' for more details about your app.

5)  Clone your site
$ rhc git-clone mysite
Or
D:\> rhc git-clone mysite
.......................
Your application Git repository has been cloned to "D:\mysite"

6)  #”D:\mysite>” is the location we cloned.
D:\mysite> git remote add upstream -m master git://github.com/rancavil/django-openshift-quickstart.git

D:\mysite> git pull -s recursive -X theirs upstream master

7)  D:\mysite> git push
remote : ................
remote: Django application credentials
               user: admin
               xertefkefkt

remote: Git Post-Receive Result: success
.............

8)  D:\mysite>virtualenv venv --no-site-packages
D:\mysite>venv\Scripts\activate.bat
<venv> D:\mysite> python setup.py install
creating .....
Searching for Django<=1.6
.............
Finished processing dependencies for mysite==1.0

9)  Change admin password
<venv> D:\mysite\wsgi\openshift> python manage.py changepassword admin
password:
...
Password changed successfully for user 'admin'
<venv> D:\mysite\wsgi\openshift> python manage.py runserver
Validating models….

10) Git add
<venv> D:\mysite> git add.
<venv> D:\mysite> git commit -am"activating the app on Django / Openshift"
   .......
<venv> D:\mysite> git push



#----------------------------------------------------------------------------------
#-----------Edit your setup.py in mysite with packages you want to install----------

from setuptools import setup

import os

# Put here required packages
packages = ['Django<=1.6',  'lxml', 'beautifulsoup4', 'openpyxl']

if 'REDISCLOUD_URL' in os.environ and 'REDISCLOUD_PORT' in os.environ and 'REDISCLOUD_PASSWORD' in os.environ:
     packages.append('django-redis-cache')
     packages.append('hiredis')

setup(name='mysite',
      version='1.0',
      description='OpenShift App',
      author='Tanveer Alam',
      author_email='xyz@gmail.com',
      url='https://pypi.python.org/pypi',
      install_requires=packages,
)
Tanveer Alam
  • 5,185
  • 4
  • 22
  • 43
3

These are steps that works for me: I've done some steps manually, but you can automate them later to be done with each push command.

  1. Create new django app with python-3.3 from website wizard
  2. Add mysql cartridge to app (my option is mysql)
  3. git clone created app to local
  4. add requirements.txt to root folder
  5. Add myapp to wsgi folder
  6. Modify application to refer to myapp
  7. execute git add, commit, push
  8. Browse app and debug errors with "rhc tail myapp"
  9. connect to ssh console

    rhc ssh myapp

10.execute this

source $OPENSHIFT_HOMEDIR/python/virtenv/venv/bin/activate
  1. install missing packages if any
  2. go to app directory

    cd ~/app-root/runtime/repo/wsgi/app_name

  3. do migration with:

    python manage.py migrate

  4. create super user:

    python manage.py createsuperuser

15.Restart the app

Serjik
  • 10,543
  • 8
  • 61
  • 70
1

This is helpful for me take a look

http://what-i-learnt-today-blog.blogspot.in/2014/05/host-django-application-in-openshift-in.html

GrvTyagi
  • 4,231
  • 1
  • 33
  • 40