Put Your App Online With OpenShift

Created by Katie Miller, @codemiller

Get OpenShift

OpenShift is a cloud computing Platform as a Service (PaaS) that makes it easy to deploy apps online. It is open source and written in Ruby.

To get started create an OpenShift Online account, which allows you to put three apps online for free. Once you are signed up, install the OpenShift RHC Client Tools by running these commands in a terminal and following the prompts:

gem install rhc
rhc setup

The above instructions assume you installed Ruby using RVM or RailsInstaller. If you used another approach, there is more info about installing RHC for different set-ups in this guide (you may need to do sudo gem install rhc).

COACH: Talk about the benefits of deploying to a PaaS such as OpenShift, as opposed to traditional servers. Discuss SSH and why we need to upload a public key to communicate securely.

Preparing your app

Create OpenShift application

We are going to create an OpenShift Ruby application with a PostgreSQL database, using a sample OpenShift Rails application as our starting point. Before we do that, in your terminal change to the parent directory of the one containing your railsgirls code, probably called projects. The cd command below will take you there if you are currently in your railsgirls directory; if not, substitute another cd command.

cd ..
pwd

The output from the pwd or ‘present working directory’ command should show you are now in the projects directory (or whatever your parent directory was called). To create the OpenShift app in the cloud and make a local copy of its contents, run the following command in your terminal:

rhc app create openshiftapp ruby-1.9 postgresql-9.2 --from-code=https://github.com/openshift/rails-example.git

The terminal output should include a URL; open a browser window and go to the application URL to view the sample Rails application (the URL will have the form http://openshiftapp-yourdomain.rhcloud.com).

COACH: Explain what Git is and why we use version control systems.

Add version control

We now have a sample app running in the cloud, but we actually need only a few pieces from its codebase. Before we copy across the bits we require, we should put our Rails Girls app under version control with Git.

Change back to your railsgirls app directory and initialize it as a Git repository with the following commands:

cd railsgirls
git init

We don’t want the pictures uploaded during app development to be part of our repository, so run the following command to instruct Git to ignore them:

echo "public/uploads" >> .gitignore

Add and commit all your app files to the Git repository with the following commands:

git add --all
git commit -m "First commit of Ideas app"

COACH: Explain the Git commands used and .gitignore.

Copy sample app code

We need the .openshift directory and config/database.yml file from the sample application in order for our Rails app to run on OpenShift. Copy these from the openshiftapp directory to the railsgirls directory. You can use Windows Explorer or another graphical file system tool to do this if you like, or alternatively run the following commands from the railsgirls directory in your terminal:

cp -r ../openshiftapp/.openshift .
cp ../openshiftapp/config/database.yml config
xcopy /e /i ..\openshiftapp\.openshift .openshift
copy ..\openshiftapp\config\database.yml config

Add and commit the new and changed files in Git with the below commands.

git add --all
git commit -m "Added OpenShift config"

Change database

The next step is to change our Rails Girls app database from SQLite to PostgreSQL. Open your application’s Gemfile and replace:

gem 'sqlite3'

with

gem 'sqlite3', :group => [:development, :test]
gem 'pg', :group => [:production]

Do a bundle to set up your dependencies:

bundle install --without production

On some platforms, this may generate platform-specific versions of your Gems that cause issues when you push your app to the cloud. To prevent this, open your Gemfile.lock file and check the versions of the ‘sqlite3’ and ‘pg’ Gems. If they have a platform-specific suffix, such as -x86-mingw32, remove this (eg. change pg (0.16.0-x86-mingw32) to pg (0.16.0) and sqlite3 (1.3.8-x86-mingw32) to sqlite3 (1.3.8)). Save and close the file, and run the above bundle command again before continuing.

Add and commit your changes in Git:

git add --all
git commit -m "Changed database to PostgreSQL"

COACH: Talk about relational databases and the differences between SQLite and PostgreSQL.

Deploy app to OpenShift

We are now ready to deploy the Rails Girls app to OpenShift. We need to tell our Git repository where to push the code. To get the location of your OpenShift code repository, run the following command, and copy the Git URL from the output.

rhc app show openshiftapp

Now run the following commands, replacing the SSH string with your Git URL. We are using ‘-f’ for force here because we are happy to wipe away the history of the current OpenShift repository, which contains the sample Rails app. When you are pushing future changes, you can just use ‘git push’.

git remote add openshift ssh://0123456789abcdef01234567@openshiftapp-yourdomain.rhcloud.com/~/git/openshiftapp.git/
git push -f --set-upstream openshift master

Refresh the app in your browser to see the result.

COACH: Talk about Git remotes.

Add environment variables

The app should be looking pretty good now, but there are some potential issues lurking because of the ephemeral nature of the deployment. When we push a new version of the application, anything stored within OpenShift’s copy of the repo will be wiped to make way for the new files. This includes some log files and the images uploaded by users. To fix this, we can store these files in persistent directories on OpenShift instead; the filepaths of the locations we need are stored in environment variables.

COACH: Explain the motivation for using environment variables.

Redirect production logging

To change the location of the production log, open config/environments/production.rb.

Beneath the comment line:

# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)

Add the line:

config.logger = ActiveSupport::Logger.new(File.join(ENV['OPENSHIFT_RUBY_LOG_DIR'], "production.log"))

Rails 3 users: Change ‘ActiveSupport::Logger’ to ‘ActiveSupport::BufferedLogger’.

You can tail your application’s logs with the command rhc tail openshiftapp (the output from the change you just made won’t show up until the new file has been committed and pushed to OpenShift).

COACH: Discuss the value of application logging.

Persist uploaded images

The directory where uploaded pictures are currently stored is within the app repository, so it will be deleted when we rebuild. To switch the uploads directory to one that will persist, open app/uploaders/picture_uploader.rb and replace

def store_dir
  "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end

with

def store_dir
  prefix = ENV['OPENSHIFT_DATA_DIR'] ? "#{ENV['OPENSHIFT_DATA_DIR']}/" : ""
  "#{prefix}uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end

def url
  return "/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}/#{File.basename(file.path)}" if ENV['OPENSHIFT_DATA_DIR'] && file
  super
end

Now uploaded images will be stored in a persistent directory, but they will still be available through the same URL as what we were using previously. To make this work, we also need to add a symbolic link on the filesystem from the repository location to the real storage location. To do this, open .openshift/action_hooks/build and add the following code:

mkdir -p $OPENSHIFT_DATA_DIR/uploads
ln -sf $OPENSHIFT_DATA_DIR/uploads $OPENSHIFT_REPO_DIR/public/uploads

This action hook code will run every time the OpenShift app is built, so the link between the directories will always be there when it’s needed.

Commit your changes and push them to the cloud:

git add --all
git commit -m "Added OpenShift environment variables"
git push

The images you uploaded before making this change will no longer display, but anything uploaded now will stick around between app rebuilds.

COACH: Explain symbolic links.

Push code to GitHub

Now that your application is under source control with Git, you may also wish to share a copy with others on a Git repository website such as GitHub. To push your code to a GitHub repository, create a repository on GitHub and copy the HTTPS string (something like https://github.com/username/reponame.git).

Navigate to your OpenShift app repository in the terminal and enter the following commands, replacing the HTTPS location with the string you copied:

git remote add github https://github.com/username/reponame.git
git push github master

The ‘master’ branch of the local copy of your repository will be pushed to GitHub. Go to the GitHub website to check it out.

COACH: Talk about Git branches and the benefits of open source code.

Conclusion

Your Rails app is now running in the cloud on OpenShift. You can push whatever other changes you like and share the URL to show off your app to your friends.