New RHSCL-based Docker images that are now in beta let you easily build your own application containers even without writing any Dockerfiles. Here is an example of a Ruby on Rails application built with the Ruby 2.2 image using the PostgreSQL 9.4 image as a database backend.

For building the application image we will use a tool called source-to-image (s2i, formally sti) which is a program that can build your application image on top of s2i images. For example the latest version of OpenShift uses s2i images to run your applications as well and you can use them with source-to-image to containerize your own applications locally.

Prerequisites

In this blog post I assume you are running RHEL 7 and you have the latest Docker from rhel-7-server-extras-rpms channel and that you enabled rhel-server-rhscl-7-beta-rpms channel for getting the source-to-image tool.

Database setup

To use PostgreSQL image we need to provide the database user, password and name. We also need to map ports from the container to the host and map the data directory from the container to somewhere else.

For now let’s assume we want to use /data directory to store our application data:

The command above run RHSCL rhscl_beta/postgresql-94-rhel7 image in the background (-d) with the required username (app), password ($APP_DATABASE_PASSWORD from the environment) and name (app_production) while mapping the PostgreSQL standard port 5432 to the same one on the host (-p). -v option at the end then specifies volume mounts telling Docker to use our /data directory. We call this container db (--name). The name just makes it easier to reference it in the next steps.

Use docker ps command to check that the database is running as expected (if the database is not running, it was stopped for some reason):

Rails application setup

For our example we need a Rails application powered by PostgreSQL database. We could use any Rails app from any remote git repository, but for the sake of completeness we create one. Therefore we need to install some dependencies first:

We need libxml2-devel, ruby-devel, postgresql-devel, gcc-c++, patch, redhat-rpm-config for installing Ruby on Rails and application dependencies, git for creating a repository and curl for checking out the results.

Once done, install Ruby on Rails and create a brand new application with the PostgreSQL backend:

$ gem install rails
$ rails new app --database=postgresql && cd app

To take advantage of our PostgreSQL database we build a simple ToDo lists management into our app:

As you can see we will want to connect to the $APP_DATABASE_NAME database with the $APP_DATABASE_USER database user and $APP_DATABASE_PASSWORD password to a PostgreSQL running on a given $APP_DATABASE_HOST host.

And run bundle command to create Gemfile.lock:

RAILS_ENV=production bundle

As we are finished building the application let’s check it in the source control:

The latest upstream version of source-to-image tool should not require the git repository to be created, but old versions do.

Building the application container

To build the application container we will use RHSCL-based rhscl_beta/ruby-22-rhel7 image with Ruby 2.2 and source-to-image tool. rhscl_beta/ruby-22-rhel7 is s2i image meaning it contains assemble s2i script that can build the application image for us.

Install source-to-image if you haven’t yet and create a new application image called app:

$ sudo s2i build file:///$PWD rhscl_beta/ruby-22-rhel7 app

First argument is our current working directory (file:///$PWD, it could be any git repository), second is the name of our s2i image and last the name of the new application image to create.

By default it will use production environment which we want, but you could change RACK_ENV variable to something else in .s2i/environment file to avoid it.

We have just build a Rails application in a container without writing any Dockerfile, how nice!

Running the containers

Our database container is already running, but to run our Rails application container we need to set two things. Database access and secret key base (a long randomized string which is used to verify the integrity of signed cookies used in Rails by default).

(Yes, we could avoid that by using Docker linking ability by specifying DB_PORT_5432_TCP_ADDR instead of APP_DATABASE_HOST in our config/database.yml. We would then run our application image with --link db:db option.)

But let’s not forget that this is our new application and so we did not even run our database migrations which has to be done beforehand. The commands themselves will be pretty similar. First we run rake db:migrate and later we run our container in the background (-d) without arguments which will run the container entrypoint (in our case the s2i run script which will eventually run rackup).

As with our database image we needed to specify all the required environment variables — for connecting to the database, RAILS_ENV=production for the production setup of the Rails app and -p 8080:8080 to map the container port to the same one on the host. In the last command we also name our container as app.

That should mean everything works. You can now visit http://0.0.0.0:8080/todo_lists in your browser, add some items and check that our PostgreSQL database at /data/userdata/ is getting filled up.

And that’s it! We created a new application image for our Ruby on Rails application with source-to-image tool and RHSCL Ruby 2.2 image and made it to save data to /data using the PostgreSQL RHSCL image.