Blog

Deploying a Rails 5 App with MongoDB, Redis, and CarrierWave to IBM Bluemix

Nick Herman

ibm-bluemix-rails5-mongodb-object-storage-redis-v2

In this post, we show how to deploy a Rails 5 application with MongoDB as a database and CarrierWave for image processing to Bluemix. The source code for the article is available here.

Keep in mind one slight difference: in the post, credentials are set in a more explicit way with user-defined environment variables, while in the repository, they are fetched from the Cloud Foundry application auto-generated VCAP_SERVICES variable.

 

Prerequisites

To follow the steps of this tutorial, you need:

  • a Bluemix account
  • cf
  • swift (Python client)

 

Adding and configuring services

Before deploying, you need to create services instances for your application. You can do it through the CLI or the UI. Note that a free MongoDB service hosted by Bluemix is not available in the UI. In addition, some configuration options have to be specified in the manifest.yml file.

 

Adding services through the CLI

The organization you intend to use and the space within it should be created in the Bluemix UI before you authenticate with cf login. They can have any names that you choose.

adding-ibm-bluemix-services-via-cloud-foundry-cli-v1

After creating a new service, you should bind it to your application as explained in the Bluemix Docs. Alternatively, you can specify dependencies names in manifest.yml, and then cf push will do it for you.

For adding a service from the command line, use cf create-service. Here is its syntax:

cf create-service SERVICE PLAN SERVICE_INSTANCE

where:

  • SERVICE is the service name.
  • PLAN is the service plan.
  • SERVICE_INSTANCE is the name of your service instance. It is an instance alias that is meaningful to you.

Find more information in the Cloud Foundry Docs.

First, we need to set up our MongoDB.

cf create-service mongodb 100 mongodb01
cf set-env APP-NAME DATABASE_URL “YOUR_MONGODB_URI”

After that, configure the database connection in your config/mongoid.yml:

...
production:
  clients:
    default:
      uri: <%= ENV[‘DATABASE_URL’] %>

We will also need the Object Storage service and Redis:

# Object Storage
cf create-service Object-Storage Free ostorage01
cf set-env APP_NAME OSTORAGE_CREDENTIALS ‘{“auth_url”:...}’ # Get credentials from the Bluemix console.

# Redis
cf create-service rediscloud 30mb redis01
cf set-env APP_NAME REDIS_URL "http://rediscloud:password@hostname:port"

If you store the Object Storage credentials in an environment variable as described above, your CarrierWave initializer should look similar to mine. Note that you should choose the fog-openstack gem version 0.1.2 or later to use Bluemix Object Storage in your application.

config/initializers/carrierwave.rb:

CarrierWave.configure do |config|
  if Rails.env.production?
    creds = JSON.parse(ENV['OSTORAGE_CREDENTIALS'])
    config.storage = :fog
    config.fog_credentials = {
      provider:               'OpenStack',
      openstack_auth_url:     creds['auth_url'] + '/v3/auth/tokens',
      openstack_api_key:      creds['password'],
      openstack_project_id:   creds['projectId'],
      openstack_userid:       creds['userId'],
      openstack_region:       creds['region'],
      openstack_temp_url_key: ENV['OS_TEMP_URL_KEY'],
      openstack_auth_omit_default_port: true
    }
    config.fog_directory  = 'your_ostorage_container_name'
    config.fog_public     = false
    config.fog_authenticated_url_expiration = 600
  end
end

Because we use MongoDB instead of PostgreSQL, we have to provide ActionCable with Redis configuration. The following configuration file addresses this issue:

config/cable.yml:

production:
  adapter: redis
  url: <%= ENV[‘REDIS_URL’] %>

To use Object Storage, you need to create a container and set the fog_directory to its name. Also, you need TEMP_URL_KEY—a random secret string—to generate public URLs for your images. To do so, run the following commands:

swift --os-auth-url 'https://identity.open.softlayer.com/v3' --auth-version 3 --os-project-id PROJECT_ID --os-region REGION --os-user-id USER_ID --os-password PASSWORD post -m 'Temp-URL-Key:YOUR_KEY'
cf set-env APP_NAME OS_TEMP_URL_KEY YOUR_KEY

 

Adding services through the UI

Note that sometimes you can choose between different offerings for the same tool in the Bluemix services catalog. For example, you have two options for Redis: Redis Cloud and Redis by Compose.

adding-ibm-bluemix-services-via-ui-v1

The last one gives you a configuration that is pre-tuned for high availability, includes additional security features, and also provides a number of metrics; the same is true for MongoDB.

ibm-bluemix-mongodb-metrics-v1

MongoDB Compose metrics

 

After you create all services, you should set the environment variables—DATABASE_URL, REDIS_URL, OSTORAGE_CREDENTIALS, and OS_TEMP_URL_KEY—according to their credentials.

ibm-bluemix-mongodb-redis-environment-variables-v1

Setting environment variables in the Bluemix UI

 

ibm-bluemix-mongodb-object-storage-credentials-v1

Reading services credentials on the Bluemix website

 

Manifest.yml

The manifest.yml file consists of two sections. The first section—declared-services—describes services that an application uses. Here is this section for the sample application:

declared-services:
  mongodb01:
    label: Rails 5 blog MongoDB
    plan: 100
  ostorage01:
    label: Rails 5 blog Object Storage
    plan: Free
  redis01:
    label: Rails 5 blog Redis
    plan: 30mb

The keys are the names of the services that are to be referenced later. The values specify the services labels and plans.

The second section—applications—describes the application itself. Here is this section for the sample application with the properties defined below.

applications:
- name: rails-5-blog
  memory: 256M
  instances: 1
  path: .
  stack: cflinuxfs2
  buildpack: https://github.com/ddollar/heroku-buildpack-multi.git
  command: bundle exec puma -e production -p $PORT
  services:
    - mongodb01
    - ostorage01
    - redis01

where:

  • name is the application name as it is shown in your Bluemix console.
  • memory is the amount of RAM that is reserved per one instance of the application excluding services.
  • instances is the number of instances to start.
  • path is a relative path to the project that is deployed. It can be a folder for Ruby or, for example, a war/jar file for Java.
  • stack is the Cloud Foundry image for the application. The cflinuxfs2 image is based on Ubuntu 14.04 (Trusty), and it is the most common choice for Ruby applications.
  • buildpack is a Git or local path to the used buildpack. For plain Ruby applications, it is typically https://github.com/cloudfoundry/ruby-buildpack.git. To use wkhtmltopdf in the example, we refer to the buildpack that lets to specify multiple buildpacks for one application. In this case, the used buildpacks are included in the .buildpacks file.
  • command defines what command to run for starting the application. It has to be a foreground program, and the default start timeout is 60 seconds. Note that your application should listen to the port specified with the $PORT environment variable and not to the port 80 that is used as an upstream for the Nginx server.
  • services lists the names of all services bound to the application. These services should be described in the declared-services section mentioned above.

 

Deploying the application

To deploy, you can just go to your application directory and run cf push. (Of course, you need to use cf login for the first time.) For real-world applications, you might need something more powerful:

cloud-foundry-cli-cf-push-result-v1

CLI: cf push result

build-and-deploy-in-ibm-bluemix-v1

Build and deploy in Bluemix

 

If you want to use background jobs in your Rails application, check out Cloud Foundry Docs. Notice that your application needs to be deployed twice in this case.


Related tutorials:


About the authors:

Nick Herman is a software engineer at Altoros. He specializes in web development using Ruby and JavaScript as his primary tools. Nick also has professional interests and expertise in many other areas related to software engineering, including programming languages and cloud technologies. You can find him on GitHub.

Dzmitry Bardziyan is a Ruby and JavaScript developer at Altoros. He has solid knowledge of Rackspace, AWS, SoftLayer, vSphere, and other infrastructure solutions as well as background in system administration. Dzmitry also contributes to a number of IT magazines.


For the next parts of this series, subscribe to our blog or follow @altoros.

Get new posts right in your inbox!

1 Comment
  • Great tutorial Nick & Dzmitry – thanks for mentioning Redis Cloud! BTW, it looks like the BlueMix compose offer is only for the free tier at the moment, but I guess that would change in the future.

Benchmarks and Research

Subscribe to new posts

Get new posts right in your inbox!