Create a new Rails project with Docker compose
This guide shows you how to use Docker Compose to set up and run a Rails/PostgreSQL app.
Define the project
We need to define four files to start a complete Rails project with Docker:
- Dockerfile
- docker-compose.yml
- Gemfile
- Gemfile.lock
Let’s start with the Dockerfile
. This file defines an image with a Docker container with Ruby and its dependencies. The application code will be located in the myapp
directory.
# Dockerfile
FROM ruby:2.5.0
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
We will need an existent Gemfile
and Gemfile.lock
. The Gemfile.lock
is just an empty file:
$ touch Gemfile.lock
About the Gemfile
we just need to create a bootstrap one to load Rails. It will be overwriteen with the call to rails new
.
# Gemfile
source 'https://rubygems.org'
gem 'rails', '5.1.5'
Finally, create a docker-comspose.yml
file:
# docker-compose.yml
version: '3'
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
tty: true
stdin_open: true
See that we have defined a couple of services: web
and db
, and that web
depends on db
. That means that the web knows the existence and have access to the database.
Build the project
Having those files created, you just need to run next command:
docker-compose run web rails new . --force --database=postgresql
You will see that the content of Gemfile
has changed after this last command. Remember that the Dockerfile
moves this file into the image and we have now a different one. Because of this change, you need to build again:
docker-compose build
Connect the database
The service of the databse is called db
in the docker-compose.yml
. We need to configure the database.yml
in order to access to this service. To do so, we need to add the host
and the username
part of the file:
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
Postgres port
By default, postgres opens the port 5432
. If you have a running local instance of postgres this port will be already opened and you won’t be able to run the Docker one. Given that case you have two options:
- stop your local instance of postgres
- change the port that uses your docker in you image. That could be done adding a
port
tag in thedb
configuration indocker-compose.yml
.
Try it!
Run migrations:
docker-compose run web bundle exec rails db:create db:migrate
This will run all the services:
docker-compose up
This will run an specific service and its dependencies:
docker-compose run --service-ports web
From here, you can work as always. Maybe it’s timne to create a new model. Remeber that you have to use docker in any call:
docker-compose run web bundle exec rails g model User name:string