Set up Docker for Rails development
Docker is a great tool to synchronize dev envinronment on different machine. This resolves the excuse "not work on my machine". This also helps new devs to quickly set up the project without scratching their head with all the missing libs, mismatch versions, etc.
This article will describe how to setup Docker and Docker Compose for a Rails app that uses Postgresql/MySQL as database, Sidekiq and Redis.
Software versions use in this article
Docker version 18.03.1-ce, build 9ee9f40
docker-compose version 1.21.2, build a133471
Ruby 2.6.1
Rails 5
Postgres 10.6
MySQL 5.7.22
Redis 4.0.9
Table of Contents:
- Install Docker and Docker Compose
- Dockerfile
- Docker Compose file
- .dockerignore
- Build and run
- References
Install Docker and Docker Compose
Installation guides for Docker and Docker Compose are well written in Docker docs.
Dockerfile
FROM ruby:2.6.1
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /demoapp
WORKDIR /demoapp
COPY Gemfile /demoapp/Gemfile
COPY Gemfile.lock /demoapp/Gemfile.lock
RUN bundle install
COPY . /demoapp
Docker Compose file
version: '3'
services:
db:
image: mysql:5.7.22
volumes:
- ./tmp/db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=123456
redis:
image: redis:4.0.9
volumes:
- ./tmp/redis:/data
web:
depends_on:
- db
- redis
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/demoapp
ports:
- 3000:3000
environment:
- REDIS_URL=redis://redis:6379/
sidekiq:
depends_on:
- db
- redis
build: .
command: sidekiq -C config/sidekiq.yml
volumes:
- .:/demoapp
environment:
- REDIS_URL=redis://redis:6379/
If the app uses PostgreSQL instead of MySQL, the DB image will be like follow:
db:
image: postgres:10.6
volumes:
- ./tmp/db:/var/lib/postgresql/data
If the app uses MongoDB:
version: '3'
services:
mongodb:
image: mongo
ports:
- "27017:27017"
web:
...
depends_on:
- mongodb
Then we'll need to update config/database.yml
to point to the DB image:
For MySQL
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password: 123456
host: db
development:
<<: *default
database: demoapp_development
test:
<<: *default
database: demoapp_test
For PostgreSQL
default: &default
adapter: postgresql
encoding: unicode
username: postgres
password:
host: db
pool: 5
development:
<<: *default
database: demoapp_development
test:
<<: *default
database: demoapp_test
For MongoDB we'll need to update config/mongoid.yml
development:
clients:
default:
database: development
hosts:
- mongodb
See more for MongoDB setup and troubleshooting notes here
.dockerignore
We could also add .dockerignore
to the root directory of Rails app, this file is optional and it works similarly to .gitignore
. This file is useful to declare list of files/directories that should be excluded from Docker build.
For example, since we use ./tmp/
to store database and redis data we should ignore it from Docker build.
./tmp/*
Build and run
For the first time run
docker-compose build
to build neccessary images. Then run
docker-compose up
to start the whole stack.
Since the app is now running in Docker containers instead of your host OS, the regular commands, rake tasks need to be run inside the container as well. For example to create and migrate database for the first time
docker-compose run web rake db:create db:migrate db:seed
Another thing to note is that when Gemfile
changed, we need to rebuild web
and sidekiq
images
docker-compose run web bundle
docker-compose run sidekiq bundle
docker-compose up --build