Rack and the Beanstalk
AWS Elastic Beanstalk manages your web application via Java, Tomcat and the Amazon cloud infrastructure. This means that in addition to Java, Elastic Beanstalk can host applications developed with languages compatible with the Java VM.
This includes tools such as Clojure, Scala and JRuby – in this post we start to think out of the box, and show you how to run any Rack based Ruby application (including Rails and Sinatra) on the Elastic Beanstalk platform. You get all the benefits of deploying to Elastic Beanstalk: autoscaling, load balancing, versions and environments, with the joys of developing in Ruby.
We’ll package a new Rails app into a Java .war file which will run natively through JRuby on the Tomcat application server. There is no smoke and mirrors here – Rails will run natively on JRuby, a Ruby implementation written in Java.
If you’ve not used Java or JRuby before, you’ll need to install them. Java is available for download, or via your favourite package repository and is usually already installed on Mac OS X. The latest version of JRuby is available here. It’s just a case of downloading the latest binaries for your platform (or source, if you are so inclined), and unpacking them into your path – full details here. I used v1.5.6 for this post.
Ruby applications and modules are often distributed as Rubygems. JRuby maintains a separate Rubygem library, so we’ll need to install a few gems to get started including Rails, the Java database adaptors and warbler, which we’ll use to package our application for deployment to AWS Elastic Beanstalk. Assuming you added the jruby binaries to your path, you can run the following on your command line:
jruby -S gem install rails
jruby -S gem install warbler
jruby -S gem install jruby-openssl
jruby -S gem install activerecord-jdbcsqlite3-adapter
jruby -S gem install activerecord-jdbcmysql-adapter
To skip the lengthy documentation generation, just throw ‘–no-ri –no-rdoc‘ on the end of each of these commands.
A new hope
We can now create a new Rails application, and set it up for deployment under the JVM application container of Elastic Beanstalk. We can use a preset template, provided by jruby.org, to get us up and running quickly. Again, on the command line, run:
jruby -S rails new aws_on_rails -m http://jruby.org/rails3.rb
This will create a new Rails application in a directory called ‘aws_on_rails’. Since it’s so easy with Rails, let’s make our example app do something interesting. For this, we’ll need to first setup our database configuration to use our Java database drivers. To do this, just define the gems in the application’s Gemfile, just beneath the line that starts gem ‘jdbc-sqlite3’:
gem ‘activerecord-jdbcmysql-adapter’, :require => false
Now we setup the database configuration details – add these to your app’s config/database.yml file.
If you don’t have a MySQL database, you can create one quickly using the Amazon Relational Database Service. Just log into the AWS Management Console, go to the RDS tab, and click ‘Launch DB instance’. you can find more details about Amazon RDS here. The hostname for the production settings above are listed in the console as the database ‘endpoint’. Be sure to create the RDS database in the same region as Elastic Beanstalk, us-east and setup the appropriate security group access.
We’ll create a very basic application that lets us check in to a location. We’ll use Rails’ scaffolding to generate a simple interface, a controller and a new model.
jruby -S rails g scaffold Checkin name:string location:string
Then we just need to migrate our production database, ready for the application to be deployed to Elastic Beanstalk:
jruby -S rake db:migrate RAILS_ENV=production
Finally, we just need to set up the default route. Add the following to config/routes.rb:
root :to => “checkins#index”
This tells Rails how to respond to the root URL, which is used by the Elastic Beanstalk load balancer by default to monitor the health of your application.
We’re now ready to package our application, and send it to Elastic Beanstalk. First of all, we’ll use warble to package our application into a Java war file.
jruby -S warble
This will create a new war file, named after your application, located in the root directory of your application. Head over to the AWS Management Console, click on the Elastic Beanstalk tab, and select ‘Create New Application’. Setup your Elastic Beanstalk application with a name, URL and container type, then upload the Rails war file.
After Elastic Beanstalk has provisioned your EC2 instances, load balancer and autoscaling groups, your application will start under Tomcat’s JVM. This step can take some time but once your app is launched, you can view it at the Elastic Beanstalk URL.
Congrats! You are now running Rails on AWS Elastic Beanstalk.
By default, your application will launch under Elastic Beanstalk in production mode, but you can change this and a wide range of other options using the warbler configuration settings. You can adjust the number of instances and autoscaling settings from the Elastic Beanstalk console.
Since Elastic Beanstalk is also API driven, you can automate the configuration, packaging and deployment as part of your standard build and release process.