Build a JRuby on Rails application from scratch and Dockerize it!

Published Feb 19, 2018Last updated May 24, 2018

About me

I'm a Ruby developer with several years of experience building and maintaining Ruby applications.

The problem I wanted to solve

I was reading the book "Deploying with JRuby 9k" and by experimenting with it, turns out the book is completely outdated. But I was able to pick some of the stuffs that I knew will be needed to accomplish my objective: Creating a JRuby on Rails and be able to Dockerize it.

My JRuby on Rails application

So, I built a JRuby on Rails application, a very basic but functional application that simply renders the default Rails welcome page. This application can be executed in Docker which is great since you will be able to deploy it on different clouds like DigitalOcean or EC2 or anything like that.

Tech stack

The process of building JRuby on Rails application from scratch

First you gotta make sure you have Java 8 installed in your computer, then install JRuby, and generate the new Rails application rails new app_name_here.

Now you have the Rails application but it still needs a lot of changes. Lets begin by changing the Gemfile, replace gem 'activerecord-jdbcsqlite3-adapter' with ´gem 'activerecord-jdbcpostgresql-adapter', github: 'jruby/activerecord-jdbc-adapter', branch: '50-stable'´ because we will be using Postgresql. Add this gem gem 'rack-timeout', '~> 0.4'. Next add this line ruby '2.3.3', engine: 'jruby', engine_version: '9.1.15.0' after this block

This indicates that you want to use JRuby instead of Ruby.
You will also need to add gem 'dotenv-rails' in your development group.

Lets move on, and create the .env file in the application root, then put the following inside it:

# This is used by Docker Compose to set up prefix names for Docker images,
# containers, volumes and networks. This ensures that everything is named
# consistently regardless of your folder structure.
COMPOSE_PROJECT_NAME=app_name_here
# What Rails environment are we in?
RAILS_ENV=development
# Rails log level.
# Accepted values: debug, info, warn, error, fatal, or unknown
LOG_LEVEL=debug
# You would typically use `rails secret` to generate a secure token. It is
# critical that you keep this value private in production.
SECRET_TOKEN=asecuretokenwouldnormallygohere
# More details about these Puma variables can be found in config/puma.rb.
# Which address should the Puma app server bind to?
BIND_ON=0.0.0.0:3000
# Puma supports multiple threads but in development mode you'll want to use 1
# thread to ensure that you can properly debug your application.
RAILS_MAX_THREADS=1
# Puma supports multiple workers but you should stick to 1 worker in dev mode.
WEB_CONCURRENCY=1
# Requests that exceed 5 seconds will be terminated and dumped to a stacktrace.
# Feel free to modify this value to fit the needs of your project, but if you
# have any request that takes more than 5 seconds you probably need to re-think
# what you are doing 99.99% of the time.
REQUEST_TIMEOUT=30
# The database name will automatically get the Rails environment appended to it
# such as: app_name_here_development or app_name_here_production.
DATABASE_URL=postgresql://app_name_here:yourpassword@postgres:5432/app_name_here?encoding=utf8&pool=5&timeout=5000
# The full Redis URL for the Redis cache. The last segment is the namespace.
REDIS_CACHE_URL=redis://:yourpassword@redis:6379/0/cache
# Action mailer (e-mail) settings.
# You will need to enable less secure apps in your Google account if you plan
# to use GMail as your e-mail SMTP server.
# You can do that here: https://www.google.com/settings/security/lesssecureapps
SMTP_ADDRESS=smtp.gmail.com
SMTP_PORT=587
SMTP_DOMAIN=gmail.com
SMTP_USERNAME=you@gmail.com
SMTP_PASSWORD=yourpassword
SMTP_AUTH=plain
SMTP_ENABLE_STARTTLS_AUTO=true
# Not running Docker natively? Replace 'localhost' with your Docker Machine IP
# address, such as: 192.168.99.100:3000
ACTION_MAILER_HOST=192.168.99.100:3000
ACTION_MAILER_DEFAULT_FROM=you@gmail.com
ACTION_MAILER_DEFAULT_TO=you@gmail.com
# Google Analytics universal ID. You should only set this in non-development
# environments. You wouldn't want to track development mode requests in GA.
# GOOGLE_ANALYTICS_UA='xxx'
# The Redis URL.
REDIS_URL=redis://:yourpassword@redis:6379/0
# The full Redis URL for Active Job.
ACTIVE_JOB_URL=redis://:yourpassword@redis:6379/0
# The queue prefix for all Active Jobs. The Rails environment will
# automatically be added to this value.
ACTIVE_JOB_QUEUE_PREFIX=app_name_here:jobs
# The full Redis URL for Action Cable's back-end.
ACTION_CABLE_BACKEND_URL=redis://:yourpassword@redis:6379/0
# The full WebSocket URL for Action Cable's front-end.
# Not running Docker natively? Replace 'localhost' with your Docker Machine IP
# address, such as: ws://192.168.99.100:28080
ACTION_CABLE_FRONTEND_URL=ws://192.168.99.100:28080
# Comma separated list of RegExp origins to allow connections from.
# These values will be converted into a proper RegExp, so omit the / /.
#
# Examples:
# http:\/\/localhost*
# http:\/\/example.*,https:\/\/example.*
#
# Not running Docker natively? Replace 'localhost' with your Docker Machine IP
# address, such as: http:\/\/192.168.99.100*
ACTION_CABLE_ALLOWED_REQUEST_ORIGINS=http:\/\/192.168.99.100*

This file is critical, since it is the configuration for the database connection, if you do not add it your Rails app will start but it wont connect to the database.

Finally, we are ready to build the app, run the command docker-compose up --build. Be patient since this command will download many libs necesary for the virtual machine work.

After that visit 192.168.99.100:3000 and you should see the Rails welcome page!

Challenges I faced

I was struggling with putting all the pieces together, it took me a while to investigate and debug a lot of problems I had by creating this project. For example: The Rails version 5.1.x does not work with the postgresql jdbc adapter version 51, so I used the Rails version 5.0.6 and the postgresql jdbc adapter version 50-stable. The other problem was on the Puma configuration, I was unable to set the workers configuration and I still do not not how to use it without breaking the app, so I commented it.

Key learnings

If you can create a JRuby on Rails application that runs on Docker this means that you are in a new level since your app can scale much better than the tipical ROR app + Heroku combo...

Tips and advice

Final thoughts and next steps

In future lessons we will be working with the Twitalytics app, adding content to it and including powerfull features like: Deploying JRuby in the Enterprise, Managing a JRuby Application, Tuning a JRuby Application, Monitoring JRuby in Production, Using a Continuous Integration Server.