CODEX

Dockerize your Ruby on Rails App

Allen Oliver M Chun
CodeX
Published in
4 min readJan 6, 2021

--

What and Why Docker is Useful?

Docker allows you to package up an application or service with all of its dependencies into a standardized unit. This unit is typically labeled as a Docker image.

In essence, Docker allows you to containers on top of a Host OS (Ubuntu, Mac, Windows) without having difficult configuration.

Installing Docker

Download and Install Docker from https://www.docker.com/

Creating Rails App

rails new rails_docker -d postgresql
cd rails_docker
bundle install
rails server

Currently when we visit localhost:3000, it’s running from our local machine not yet from the docker image.

Setup Docker for Rails

Create a Dockerfile on the root directory of your project and add the following content.

Note: I’m currently using Rails 6.0.2.2 and Ruby 2.6.0.

FROM ruby:2.6.0-slimRUN apt-get update -qq \
&& apt-get install -y \
# Needed for certain gems
build-essential \
# Needed for postgres gem
libpq-dev \
# Others
nodejs \
vim-tiny \
# The following are used to trim down the size of the image by removing unneeded data
&& apt-get clean autoclean \
&& apt-get autoremove -y \
&& rm -rf \
/var/lib/apt \
/var/lib/dpkg \
/var/lib/cache \
/var/lib/log
# Changes localtime to Singapore
RUN cp /usr/share/zoneinfo/Asia/Singapore /etc/localtime
RUN mkdir /rails_dockerWORKDIR /rails_dockerCOPY Gemfile /rails_docker/GemfileCOPY Gemfile.lock /rails_docker/Gemfile.lockRUN bundle installADD . /rails_dockerCMD bash -c "rm -f tmp/pids/server.pid && rails s -p 3000 -b '0.0.0.0'"

Dockerfile is a human readable shell script and this does the following:

  • Fetches ruby 2.6.0-slim from DockerHub, this is the base image and it has a lightweight operating system called slim with ruby 2.6.0
  • Running the dependencies
  • Changing the image timezone to Singapore (or change it depending on the timezone you want)
  • Creating a rails_docker directory inside the image and setting this up as a work directory
  • Copying the Gemfile and Gemfile.lock from the project to the rails_docker directory image
  • Running bundle install in the image
  • Running rails app using shell command in localhost:3000

In order to run these commands, run this using

docker build .

Once the building process is finished, run `docker images` to see the list of docker images you just built.

To run the Rails app. Tag the built docker image and Run it in localhost:3000

docker tag <image-id> rails_docker:v1.0.0docker run -it -p 3000:3000 rails_docker:v1.0.0 bundle exec rails server -b 0.0.0.0 -p 3000

Run the Rails app using docker-compose

We now have a working Ruby on Rails app on top of Docker.

We may also want to use other services like Postgres, Redis, Sidekiq. To achieve this we can use docker-compose

Create a docker-compose.yml in the root directory of our project.

version: '3'
services:
db:
image: postgres:alpine
restart: always
volumes:
- ./tmp/db:/var/lib/postgresql/data
ports:
- "5432:5432"
app:
build: .
restart: always
command: bash -c "rm -f tmp/pids/server.pid && rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/rails_docker
- bundle_path:/bundle
ports:
- "3000:3000"
depends_on:
- db
volumes:
bundle_path:

In this configuration file. We define 2 services:

  • Postgres as our DB. It’s currently using an image came from DockerHub. It’s currently running on port 5432 of host OS
  • Rails App which depends on db and running on port 3000

We also added the restart flag to always so that even we restart the host OS, the docker image will still run.

List all the running docker images using docker ps after running docker-compose up

Access Rails App using http:localhost:3000

We also need to change our database.yml to connect to our postgres image.

default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") %>
development:
<<: *default
database: rails_docker_development
host: db
username: postgres
port: 5432

The host is now pointing to db because our postgres is running in db service

We also need to run the rake db:create db:migratemanually using

docker-compose run app rake db:create

You can also bundle install using this command by just changing the last part.

Run the application using docker-compose up

Now, you should be able to see the rails app in localhost:3000

Running Rails Console

As part of our development, it’s also important to access our database through rails console

To do this run docker ps and access the app image using docker exec -it <container_id> sh

This will access the working directory. You can also list all the folders using ls.

Access Rails console now inside the image using rails console

Distributing Image to DockerHub

To distribute the image in DockerHub. Run the following commands

  • Create account in Dockerhub
  • Create Respository
  • On the local machine run docker build -t <username>/<container_image> .
  • Push it to Dockerhub Repo using docker push <username>/<container_name>
  • To pull this image run `docker pull <username>/<container_name>

--

--

Allen Oliver M Chun
CodeX

Full Stack Software Developer based in Singapore. Software Developer since 2012. Specialized in Ruby on Rails, Vue.js. AWS Development.