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.
Download and Install Docker from https://www.docker.com/
Creating Rails App
rails new rails_docker -d postgresql
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 188.8.131.52 and Ruby 2.6.0.
FROM ruby:2.6.0-slimRUN apt-get update -qq \
&& apt-get install -y \
# Needed for certain gems
# Needed for postgres gem
# 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/log# Changes localtime to Singapore
RUN cp /usr/share/zoneinfo/Asia/Singapore /etc/localtimeRUN 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.
- "5432:5432" app:
command: bash -c "rm -f tmp/pids/server.pid && rails s -p 3000 -b '0.0.0.0'"
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
We also need to change our
database.yml to connect to our postgres image.
pool: <%= ENV.fetch("RAILS_MAX_THREADS") %>development:
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
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
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
Access Rails console now inside the image using
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>