Adding Docker to your Rails workflow

One of the challenges we face when we are developing an application, is having a uniform development stack among team …

One of the challenges we face when we are developing an application, is having a uniform development stack among team members. In this tutorial, I’ll show you how to use Docker and docker- compose to manage your rails application and simplify the project setup for new team members.

Preliminary Concepts

Before to start setting-up the application, let’s define some basic concepts:

Docker

Docker is a tool that can package an application and its dependencies in a virtual container that can run on any Linux server. This helps enable flexibility and portability on where the application can run, whether on premises, public cloud, private cloud, bare metal, etc.

Docker Logo

Docker Compose
Compose is a tool for defining and running multi-container Docker applications. It uses YAML files to configure the application’s services and performs the creation and start-up process of all the containers with a single command.

Docker Compose

This tutorial assumes that you have installed docker in you machine and you have notions about how to use docker. If you don’t have the docker engine yet, you can follow the Docker CE install instructions from the official website.

Creating a new application

First we need to create a new rails application that uses PostgreSQL as a database engine.

rails new docker-demo-app --database=postgresql

rails new

Configuring the database

The next step is to update the config/database.yml to use a basic configuration that allow to run the application without docker using the system PostgreSQL engine or use the docker configuration with a database container.

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch('DB_USERNAME') { 'user' } %>
  password: <%= ENV.fetch('DB_PASSWORD') { 'password' } %>
  host: <%= ENV.fetch('DB_HOST') { 'localhost' } %>
  port: 5432

development:
  <<: *default
  database: docker-demo-app-development

test:
  <<: *default
  database: docker-demo-app-test

production:
  <<: *default
  database: docker-demo-app-production

rails database configuration

Adding Docker files

After setting the database with our Rails application, we can add the Docker configuration files required to create the container and manage the application.

Dockerfile

The first file we need to add in the project root is the Dockerfile, this file represents the basic configuration that your application needs to run properly. If you need some compiled dependencies like graphviz, imagemagick, ffmpeg, etc. you can add the required steps to install or compile them here.


FROM ruby:2.3.3 RUN apt-get update && apt-get install -qq -y build-essential libpq-dev postgresql-client-9.4 apt-transport-https # Using Debian, as root RUN curl -sL https://deb.nodesource.com/setup_9.x | bash - RUN apt-get install -y nodejs ENV APP_HOME /usr/src/app RUN mkdir $APP_HOME WORKDIR $APP_HOME ADD Gemfile* $APP_HOME/ ADD package.json* $APP_HOME/ RUN bundle install --jobs 20 --retry 5 RUN npm install

Dockerfile

.dockerignore

This file is similar to the .gitignore file. The .dockerignore file helps us to avoid sending unnecessary or sensitive files inside the docker image.

.git
.dockerignore
.byebug_history
log/*
tmp/*

dockerignore

docker-compose.yml

We need to add the following docker-compose.yml file to our project. This file includes the environment variables required to connect it to the Postgres database container, it also uses the working directory as a volume, in this way we can edit our project in our local and all the changes will be reflected inside the container.

version: '3'

services:
  webapp:
    build: .
    depends_on:
      - postgres
    environment:
      - RAILS_PORT=3000
      - DB_USERNAME=user
      - DB_PASSWORD=password
      - DB_HOST=postgres
    volumes:
      - '.:/usr/src/app'
    ports:
      - '3000:3000'
    networks:
      - demo
    stdin_open: true
    tty: true
    working_dir: '/usr/src/app'
    command:
      - /bin/bash
      - -c
      - bundle install --jobs 20 --retry 5; npm install; rm ./tmp/pids/server.pid; rails db:setup db:seed; rails s

  postgres:
    image: postgres:9.4
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
    networks:
      - demo
    ports:
      - '5432:5432'
    volumes:
      - '../postgres:/var/lib/postgresql/data'

networks:
  demo:
    driver: bridge

Docker Compose

Start the application

Once we have added the necessary files to the project, we can start the containers using the following command:

docker-compose up

docker-compose up

If you want to start the containers without showing the container logs, you can use the -d flag.

docker-compose up -d

Note: sometimes in the first docker-compose up, the Rails application could show a database connection error like the following:

docker database error

This error is shown because the Rails container started before the Postgres container. To fix this you should restart the Rails container using:

docker-compose restart webapp

At this point you can verify the application is working in your browser at http://localhost:3000

Watch the Docker containers

Now the containers have started because of the docker-compose. You can see them using the following command in the project directory:

docker-compose ps

docker-compose ps

Interacting with the Rails application

The aim is to use docker-compose to manage the application. In the docker-compose.yml we named the rails application webapp. Now you can use the following structure to run rails commands inside the container.

docker-compose exec

Rails scaffold

docker-compose exec webapp rails generate scaffold User name:string email:string

docker compose rails scaffold

Database migration

docker-compose exec webapp rails db:migrate

docker compose rails db migrate

Note: In Linux systems it’s possible you need to add the –user flag
docker-compose exec --user "$(id -u):$(id -g)" webapp rails db:migrate

Database Resetting

docker-compose exec webapp rails db:reset

docker compose rails reset database

Rails console

docker-compose exec webapp rails console

docker compose rails console

Interacting with containers

You can use the following docker-compose commands to manage the containers. You can see the full list in the official documentation

Watching container logs

docker-compose logs

docker-compose logs

Stopping containers

docker-compose stop

docker-compose stop

Destroying containers

docker-compose down

docker-compose down

Docker is a useful tool you should consider to include in your application workflow. In this tutorial we only added two containers, but it’s quite simple to add other services like Redis or to run multiple applications simultaneously; and with a few changes to your docker-compose configuration you can deploy your project to production.

If you want to learn more, please contact us!

Keep reading

More >