Dockerize your Rails App

Nicolas Mery
Código Banana: El blog de Platanus
3 min readSep 25, 2015

This post its an introduction to containerizing your Ruby on Rails application with Docker. You will find out how to build an image of your app and how to run it.

First step: install Docker.

In Ubuntu:

wget -qO- https://get.docker.com/ | sh

If that doesn’t work, you could go to the Docker official site

In case of OSX go to Docker Installation for Mac

Build your Docker image

Now lets build a Dockerfile for your application.

# Available vers here https://registry.hub.docker.com/_/ruby
FROM ruby:2.1
MAINTAINER "Your Name <your@email.com>"ADD . /app
WORKDIR /app
RUN bundle install
CMD ["rails","s"]

This is the minimal expression of a Dockerfile. Dockerfiles are recipes for building Docker images that can run in a Docker container.

Explanation:

  • The image is based on the ruby:2.1 image
  • We ADD the code of our app to the /app folder.
  • We run bundle install to install the gems needed for our app.
  • Finally, we tell the image that our default command to run is “rails s”.

Now to build your image:

docker build -t myimage .

If you run it again you will find that it takes less time to build. Thats because docker caches the building process.

The problem with our Dockerfile is that the “ADD” line will be ran everytime that any file in our current folder changes (this includes the RUN bundle install line). That would be very annoying.

So to avoid that we do this trick:

FROM ruby:2.1MAINTAINER "Your Name <your@email.com>"ADD Gemfile /app/Gemfile
ADD Gemfile.lock /app/Gemfile.lock
WORKDIR /app
RUN bundle install
ADD . /appCMD ["rails","s"]

With those 2 lines we will be caching the bundle install command and the cache will be disabled only if the Gemfile changes.

Build again your image:

docker build -t myimage .

Running your Docker image

Run it like this:

docker run -ti myimage

You will probably get errors if your app depends on other services, i.e a database.

Identify the services that your app uses. Mysql? Redis? MongoDB?

You will find docker images for many of them here https://registry.hub.docker.com

Linking to a Database

We can run a MySQL DB from a docker image like this:

docker run -d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=mysecurepass mysql

This will run mysql as a daemon (-d) persisting the data (-v /var/lib/mysql) and setting the root pass (mysecurepass)

Now, we would like to connect to this database and there are many ways to do this but I prefer linking my app container to the db like this:

docker run -ti — link db:db myimage

When we do this, Docker creates a bunch of nice-to-have configuration so we can easily access to the service that the linked container exposes. We will be using the “db” hostname that docker creates in the /etc/hosts file of our app container.

Now this is an example database.yml for your Ruby on Rails app.

development:
adapter: mysql2
encoding: utf8
database: app_development
username: root
password: mysecurepass
host: db
port: 3306

Notice that we are using “db” as the host name of the database.

You can use this strategy with all the services you need for your app. Linking to other containers adds a lot of environmental variables some are useful. You can find out more about linking here: Docker Linking

Once you have all running, start your app and enjoy!

docker run -ti — link db:db myimage

Troubleshooting and tips

Logs and Tails

You can look at the logs of the container with docker logs

docker logs CONTAINER_ID

And you can do something similar to tail -f on the logs like this

docker logs -f CONTAINER_ID

And also you can tell the logs to only include the last 100 lines like this

docker logs -f — tail=100 CONTAINER_ID

Mount the folder app in the container

In development you might want to change the code while is running.

You can “mount” your folder in the container running it like this:

docker run -ti -v ${PWD}:/app — link db:db myimage

Enter the container

You can also run bash to “enter” to the container:

docker run -ti -v ${PWD}:/app — link db:db myimage bash

Docker Compose

docker-compose is a Docker tool that helps you manage a group of docker containers and their dependencies.
You might want to use docker-compose to facilitate the start and stop process of your app stack. You can find more information about docker-compose here

--

--

Nicolas Mery
Código Banana: El blog de Platanus

Nicolas Mery - Software Engineer & entrepreneur. Fan of: HBGA, Captology, Agile and the Lean Startup.