Dockerizing a Ruby on Rails application

In this blog you will you will learn how to set up docker on your machine and dockerize a Ruby on Rails application. The application we're going to build will make use of PostgreSQL database.  

After reading this article, you will have a basic idea of what Docker is, how it can help you as a developer, and how to run ruby on rails application on docker.

What is Docker?

Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly.  With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker’s methodologies for shipping, testing, and deploying code quickly, you can significantly reduce the delay between writing code and running it in production.

How is Docker Different from a Virtual Machine?

The basic architecture of Docker containers and Virtual machines differ in their OS support. Containers are hosted in a single physical server with a host OS, which is shared among them. Virtual machines, on the  other hand, have a host OS and individual guest OS inside each VM. Irrespective of the host OS, the guest OS can be anything – either Linux or Windows.

 In Docker, since the host kernel is shared among the containers, the container technology has access to the kernel subsystems. As a result, a single vulnerable application can hack the entire host server. On the other hand, VMs are unique instances with their own kernel and security features. They can, therefore, run applications that need more privilege and security.

Docker containers are self-contained packages that can run the required application. Since they do not have a separate guest OS, they can be easily ported across different platforms. Whereas, VMs are isolated server instances with their own OS. They cannot be ported across multiple platforms without incurring compatibility issues.

Docker and Virtual machines are intended for different purposes, so it’s not fair to measure their performance equally. But their light-weight architecture makes Docker containers less resource-intensive than the virtual machines.

Other Terms

  • Images: The file system and configuration of our application which are used to create containers.
  • Docker daemon: The background service running on the host that manages building, running and distributing Docker containers.
  • Docker client: The command line tool that allows user to interact with docker daemon.
  • Docker hub: A registry of Docker images. You can think of a registry is a directory of all available Docker images.
  • Docker compose: Compose is a tool of defining and running multi-container docker applications. With compose you use a compose file to configure your application’s services. Then, using a single command, you create and start all the services from your configuration.

Install Docker on Ubuntu

$ sudo apt-get update
$ sudo apt-get install \linux-images-extra-$(uname -r) \linux-images-extra-virtual

Set up the repository – Docker CE

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu \$(lsb_release -cs) \stable"

Install Docker CE

$ sudo apt-get update
$ sudo apt-get install docker-ce
$ sudo docker run hello-world

Manage Docker as non root user
$ sudo groupadd docker
$ sudo usermod -aG docker $USER

Log out and log back in (I had to restart my computer)

$ docker run hello-world

Install Docker compose

Example: 

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

Docker Setup On rails project

1. Create a Dockerfile
From ruby:2.3.3
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myappWORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp

2. Create a Gemfile
source 'https://rubygems.org'
gem 'rails', '5.0.0.1'

3. Create a Gemfile.lock

$ touch Gemfile.lock

4. Create docker-compose.yml file

version: '3'
services:
  db:
    image: postgres
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes: 
      - .:/myapp
    ports: 
      - "3000:3000"    
    depends_on:
      - db

5. Generate the project
$ docker-compose run web rails new . --force –database=postgresql

6. Build the containers
$ docker-compose build

7. Update the database config/database.yml

default: &default    
    adapter: postgresql
    encoding: unicode
    host: db
    username: postgres
    password:    
    pool: 5

development:    
    <<: *default
    database: myapp_development

test:     
    <<: *default    
    database: myapp_development

8. Create the database
$ docker-compose run web rake db:create

View the rails welcome page
$ docker-compose up

Go the http://localhost:3000 on your browser to see the rails welcome page.

Conclusion

Docker is awesome. Now you can run your projects on other platforms without having to worry about dependencies and platform specific gotchas. 

You get an environment that’s easy to share with fellow team members, you can model it to closely resemble your production environment, and extend it in a simple way.

The best part is that it’s easy to clean up once you’re done with aproject. You don’t pollute your computer with all those different libraries you only need for that single project!


Reference