Docker for existing Rails app with Postgresql

Shravan C
4 min readApr 24, 2020
Source: https://www.docker.com/resources/what-container

At the beginning of my career, I used to install any software or programming languages directly into my system. I was happy with that at that time. So was executing any ruby program with ruby filename.rb. Whereas Ruby has rvm to manage different versions of a ruby in your system, but I was not a fan of that and used only one version of ruby because I didn’t get any use case for that. Later I went on doing the same with the python programming language. But later I came across the use case where I needed a different version of libraries for different programs(It was for TensorFlow 1.14 and 2.1).

Then I introduced myself with virtualenv library which will help us keep different versions of python and its library and whenever we need any particular version just activate it and start using it. I felt very happy with this and gave me a very broad mind like I can screw up anything I want in that virtualenv and still have your system python version fine shine. And now, learned docker, which is one level above this virtualenv. This is another awesome thing, and this literally allows you to create a new OS in your existing OS and run everything in that space. Everything you want for the application will be installed, and the app will be up and running. This will kind of helps me share the application I develop to anyone I want and be carefree of installation procedure(Just share the command to bring up the system and then enjoy the application). It’s that simple with the docker. Further details on docker.

In this article as the title says, we will be going to create a docker file and see how we can get it up and running.

Docker installation:

Installing docker to ubuntu 18.04 can be found in this article. I used the below command to get it up and running:

sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo apt update
apt-cache policy docker-ce
sudo apt install docker-ce
sudo systemctl status docker

The docker version that I have is 19.03.6. I hope it should not matter much with different versions.

Dockerfile:

I did struggle to get the right Dockerfile, it took me like 2–3 days after many different experiments that I did. I used to follow tutorials was able to get the app they were using up and running but not my app. So I stopped all the copy-pasting and started writing the commands carefully. I followed these two articles(first and second) to come up with my docker setup for Rails and Postgres. I have tried executing the same commands as these articles suggested, but couldn’t get it working. Either Postgres issue or the rails were not able to run. This is the Docker file:

FROM ruby:2.5.1ENV BUNDLER_VERSION=2.1.2RUN apt-get update -yqq \
&& apt-get install -yqq --no-install-recommends \
postgresql-client \
nodejs \
qt5-default \
libqt5webkit5-dev \
&& apt-get -q clean \
&& rm -rf /var/lib/apt/lists
RUN gem install bundler -v 2.1.2WORKDIR /usr/src/app
COPY Gemfile* ./
RUN bundle check || bundle install
COPY . .ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"]

Just be careful with the bundler version. Try to specify the bundler version that u have installed the gems from Gemfile. If it didn’t work, try to update the bundler version, delete Gemfile.lock and then run bundle install.

docker-compose

The same story, tried from two articles, but this is my working docker-compose file:

version: "3.4"volumes:
db-data:
external: false
services:
db:
environment:
POSTGRES_USER:
POSTGRES_PASSWORD:
image: postgres:10.12
volumes:
- db-data:/usr/local/pgsql/data
app:
env_file: .env
build: .
volumes:
- .:/usr/src/app
ports:
- 3003:3003
depends_on:
- db

Again, give attention to the Postgres image.

.env file

POSTGRES_HOST=db
POSTGRES_USER=user_system
POSTGRES_PASSWORD=super_secure
SECRET_KEY_BASE=development_secret
SINGLE_TENANT_MODE=true

This is clear that it will set this as environment variables in the container for the application to use.

database.yml

# config/database.yml
default: &default
adapter: postgresql
host: <%= ENV["POSTGRES_HOST"] %>
username: <%= ENV["POSTGRES_USER"] %>
password: <%= ENV["POSTGRES_PASSWORD"] %>
encoding: utf8
min_messages: warning
pool: 2
timeout: 5000
development:
<<: *default
database: user_system_dev
test:
<<: *default
database: user_system_test
production:
<<: *default
database: user_system

This host is required to be added and rest is known. Nothing special in this, just read data from environment variables that are set in the .env file.

Gemfile

Gemfile and Gemfile.lock can be found in this repository. All the highlights are the points where I have got a doubt when my docker was failing to run in the beginning. Just thought of highlighting, hope it helps others with the same problem.

Testing

Commands are as below:

# READMEdocker-compose up --build
docker-compose up -d
docker-compose exec app bundle exec rake db:setup db:migrate
docker-compose exec app bundle exec rake db:seed

With this, you should be able to open the browser and run any get calls.

Conclusion:

Docker is a useful tool if you need to share your application without much load on the person to whom you are sharing to. It just takes a few commands that are mentioned in the above section. Containerization will help deploy your application on the cloud as well. There you go, happy learning and sharing. Enjoy coding!!!

--

--

Shravan C

Software Engineer | Machine Learning Enthusiast | Super interested in Deep Learning with Tensorflow | GCP