Working with Sinatra and Cloud Foundry
The other night I had idea pop in my head, that honestly, I was quite surprised hadn’t thought about before. I then set about working through the design of what would be needed to pull this idea off (sorry, the idea is under strict NDA that requires many pints of Guinness to even be able to sign).
Recently, I have started to move most of my work to Ruby, even working on another side project in Ruby that this project will be able to utilize. This project is a web based application, so with that, I needed a web/application server plus a platform to run it on. Now I have done my share of setting up Linux boxes with the required software before, but this time I wanted to see if the open source Cloud Foundry bits (VCAP) would prove useful in what I was looking to do. For the web/application server, I decided to go with Sinatra and Thin.
This was not my first time setting up a VCAP server or deploying apps to one. For some reason, I decided to stand up yet another VCAP VM on my laptop instead of using an existing instance :/. Of course in this process, I ran into issues, such as corrupted vmc profiles and a rvm installation issue in the soon to be deprecated default install process. Using the experimental Chef based installation, I had no issues getting a VCAP VM up and running. One interesting point to note when using the default or Chef based installation off of github, the default domain is vcap.me. When you ping vcap.me, this resolves to 127.0.0.1 :). So how do you access the VM via DNS? Well you set up an SSH tunnel from your workstation to the VCAP VM (also explained in the installation instructions).
In order to deploy applications to your VCAP VM, you need to install VMC to your workstation. This is as simple as running
gem install vmc. If you want the latest beta, add –pre behind that command like so
gem install vmc --pre. With your SSH tunnel setup and VMC installed, now you can follow the “Trying your setup” section on the VCAP github page (VCAP).
Now with VCAP up and running, I focused on getting Sinatra and Thin working. Sinatra is actually quite simple, actually. First install the Sinatra gem:
gem install sinatra
and here is a simple web application
require 'sinatra' get '/' do "Hello World" end
And that’s it. When you run ruby app.rb (or whatever you named the file), Sinatra fires up webrick and starts serving your page. See? Simple.
So lets move on. Now there are two ways to run Sinatra apps. The first is classic mode, as shown above. The second is in modular mode in a file called server.rb, shown below:
require 'sinatra/base' class Server < Sinatra::Base get '/' do "Hello World" end end
Each mode of Sinatra application is also started differently. With the classic mode, you can start it with
Sinatra::Application.run! However, in modular mode, Rack is used to start the server, and here in comes the fun of getting Sinatra/Thin working on Cloud Foundry VCAP VM. Classic mode works quite well on the VCAP VM, but modular mode requires a little bit more configuration.
First, you want to create a config.ru file in the root of your application. The location is key. By default, Rack looks for config.ru in the root of your application directory. There is a :config setting that can be changed, but for some reason when I set this key with a different config.ru location, the default port Thin starts on changed from 9292 to 8080. I have not figured out why this is occurring as nothing in my config.ru changed the Thin port; however, this will cause it to start on port 8080 in VCAP and not be accessible. The config.ru file needs to look like the following:
require 'sinatra' set :run, false #This disables Sinatra trying to start Thin and let's Rack start Thin require File.dirname(__FILE__) + "/path/to/server/file" #The following is key. Sinatra Modular apps could #be started with just run Server, but when deployed to #VCAP, you need to map the application #to a location. #In this instance, I want my server application #to be mapped to the default path. map '/' do run Server end
Ok, now that our config.ru is configured (and of course more configurations could be added to it), we need to configure our main application file. For this, we need to use Rack to start our server. Lets say this file is called app.rb
require File.dirname(__FILE__) + "/path/to/server/file" require 'rack' require 'sinatra' #required for VCAP to detect this is a Sinatra Application require 'thin' server = ::Rack::Server.new() server.start
Now before we push our application to our VCAP VM, we need to create a Gemfile that looks like the following:
source "http://rubygems.org" gem 'sinatra' gem 'thin'
You may wonder why Rack is not listed. Sinatra is dependent on Rack and will install the Rack gems when its installed. With the Gemfile created, we can run
bundle package && bundle install to package up all the gems required by our application. If you require any more gems for your application, you will want to run
bundle package && bundle install before you update your application.
With done, we need to push our application. We start this process with the command:
vmc push --runtime ruby19
If you are still using Ruby 1.8.7, do not add the –runtime ruby19. There is one more key step when pushing the application. VMC will ask for the “Application Deployment URL”. The default url it will show will be
[APPLICATION NAME].vcap.me:[SSH TUNNEL PORT]. You will receive an error if you keep the default. You will want to remove the
[SSH TUNNEL PORT] from the url, so it looks like
With that, you should see VMC staging and starting your application on your VCAP VM. When started, you can access via web browser or curl at
[APPLICATION NAME].vcap.me:[SSH TUNNEL PORT].
It took me a while to get this working, but now that is, it is working great. The next step will be to see if Sinatra-Synchrony will work as well. I do not believe my application will require this, but it is more for an academic purpose at this point.