DEV Community

Cover image for Create And Dockerize Rails Application With PostgreSQL And Sidekiq (Docker + Docker Compose)
ThinEi
ThinEi

Posted on

Create And Dockerize Rails Application With PostgreSQL And Sidekiq (Docker + Docker Compose)

For this setup, I will use the ruby version 3.1.2 which will generate the rails app of rails version 7.0.4.



rails new ecs_rails_app -d postgresql


Enter fullscreen mode Exit fullscreen mode

rails new setup

Our application is created. Let’s create Dockerfile.



cd ecs_rails_app


Enter fullscreen mode Exit fullscreen mode


# Creating Dockfile
touch Dockerfile


Enter fullscreen mode Exit fullscreen mode


# Creating development directory and docker-compose file
mkdir development && touch development/docker-compose.yml


Enter fullscreen mode Exit fullscreen mode


# Creating entrypoint.sh file
touch entrypoint.sh


Enter fullscreen mode Exit fullscreen mode

Dockerfile

Paste the following content into Dockerfile



FROM ruby:3.1.3

# install rails dependencies
RUN apt-get clean all && apt-get update -qq && apt-get install -y build-essential libpq-dev \
    curl gnupg2 apt-utils  postgresql-client postgresql-server-dev-all git libcurl3-dev cmake \
    libssl-dev pkg-config openssl imagemagick file nodejs npm yarn


RUN mkdir /rails-app
WORKDIR /rails-app

# Adding gems
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
RUN bundle install

COPY . /rails-app

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]


Enter fullscreen mode Exit fullscreen mode

Entrypoint.sh

paste the following code into entrypoint.sh file



#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /rails-app/tmp/pids/server.pid

exec "$@"


Enter fullscreen mode Exit fullscreen mode

Now build the docker image.



docker build .


Enter fullscreen mode Exit fullscreen mode

Build Docker Image

Docker Compose

I'll add Postgresql, Redis and web (our rails project) services in our docker compose file.
Firstly, we need some adjustment, database.yml file should look like this:



default: &default
  adapter: postgresql
  encoding: unicode
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>
  port: <%= ENV['DB_PORT'] %>
  host: <%= ENV['DB_HOST'] %>
  database: <%= ENV['DB_NAME'] %>
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default


Enter fullscreen mode Exit fullscreen mode

Open the docker-compose.yml file located in development folder and paste the following code:



version: "3.8"
services:
  db:
    image: postgres
    restart: always
    environment:
     - POSTGRES_HOST_AUTH_METHOD=trust
    volumes:
      - db:/var/lib/postgresql/data'
    logging:
            driver: none
    ports:
      - 5432:5432
  redis:
    image: redis:4.0-alpine
    command: redis-server
    volumes:
      - redis:/data
    ports:
      - 6379
    logging:
            driver: none
  web:
    build: ../
    command: bundle exec rails s -p 3000 -e development -b '0.0.0.0'
    environment:
     DB_USERNAME: postgres
     DB_PASSWORD: password
     DB_NAME: ecs_application_db
     DB_PORT: 5432
     DB_HOST: db
     RAILS_ENV: development
     RAILS_MAX_THREADS: 5
     REDIS_HOST: redis
     REDIS_PORT: 6379
     BUNDLE_PATH: /bundle
    volumes:
      - ../:/rails-app
      - bundle:/bundle
    ports:
      - "3000:3000"
    depends_on:
      - "db"
      - "redis"
volumes:
  db:
  bundle:
  redis:


Enter fullscreen mode Exit fullscreen mode

I have created 3 services (db, redis and web)

Our rails application requires postgresql database and redis (in the future for sidekiq). Docker compose is creating postgres and redis service for our rails application inside docker-compose.yml file.

  • db service is using postgres docker image from docker hub
  • redis service is using redis docker image from docker hub
  • web service is our rails application project containing our own Dockerfile


cd development/
docker-compose run web bundle install
docker-compose run web rails db:migrate
docker-compose run web rails db:setup
docker-compose build


Enter fullscreen mode Exit fullscreen mode

Build Docker Compose

Then run the final command to instantiate rails server



docker-compose up


Enter fullscreen mode Exit fullscreen mode

Docker Compose Up

Server started

Run Locally

Configure sidekiq

Add gems into Gemfile:



gem 'sidekiq', '< 7'
gem 'redis-rails'


Enter fullscreen mode Exit fullscreen mode

Create following files:



touch config/initializers/sidekiq.rb


Enter fullscreen mode Exit fullscreen mode

Paste following code into sidekiq.rb file



# frozen_string_literal: true
sidekiq_config = { url: "redis://#{ENV['REDIS_HOST']}:#{ENV['REDIS_PORT']}/12" }
Sidekiq.configure_server do |config|
  config.redis = sidekiq_config
end
Sidekiq.configure_client do |config|
  config.redis = sidekiq_config
end


Enter fullscreen mode Exit fullscreen mode

Go to development folder and install the new gems



docker-compose run web bundle install


Enter fullscreen mode Exit fullscreen mode

We need to add a new service to the docker-compose.yml file



  sidekiq:
    build: ../
    command: bundle exec sidekiq
    volumes:
      - ../:/rails-app
    environment:
      RAILS_ENV: development
      REDIS_HOST: redis
      REDIS_PORT: 6379
    depends_on:
      - "redis"


Enter fullscreen mode Exit fullscreen mode

then run



docker-compose up


Enter fullscreen mode Exit fullscreen mode

Docker compose up

Docker container

Then we will create a Controller, ActiveJob and some changes to the routes.

Create a controller and Active Job



docker-compose run web rails g controller home
docker-compose run web rails g job home


Enter fullscreen mode Exit fullscreen mode

home_controller.rb



class HomeController < ApplicationController
    def index
        render json: {"message": "Welcome"}
        HomeJob.perform_later
      end
end


Enter fullscreen mode Exit fullscreen mode

home_job.rb



class HomeJob < ApplicationJob
  queue_as :default
  def perform(*args)
    puts 'Job Executed'
  end
end


Enter fullscreen mode Exit fullscreen mode

routes.rb



Rails.application.routes.draw do
  get '/home', to: 'home#index'  
end


Enter fullscreen mode Exit fullscreen mode

then run



docker-compose build
docker-compose up


Enter fullscreen mode Exit fullscreen mode

Open http://localhost:3000/home in your web browser,

Localhost

in the console you should be able to see that the HomeJob has been performed.

Job Executed

Yes.

Top comments (0)