This guide shows and explains bootstrapping new Rails application using Docker. This way you don’t have to install Ruby and other tools on your host.
In my case I want to use PostgreSQL as a default database. The magic command is:
docker run --rm -v $PWD:/app -w /app ruby:2.5.1-alpine /bin/sh -c 'apk add --update build-base postgresql-dev && gem install rails -v "5.2.0" && rails new . --database=postgresql'
How does it work?
Let’s break the command down into parts:
docker run- this creates a new Docker container
--rm- remove the image after running
-v $PWD:/app- mount current directory in
-w /app- set default work directory to
ruby:2.5.1-alpine- image identifier of a ruby official repository image tagged as
2.5.1-alpine. 2.5.1 refers to the Ruby version.
alpineis a lightweight Linux distribution that weights only around 5MB.
/bin/sh -c '...'- a command to run in the Docker container. We need to run multiple commands (combined with
&&). The only way to achieve that is to run them in a shell. We use
bashbecause by default Alpine doesn’t have bash installed.
apk add --update build-base postgresql-dev- installs Rails and pg gem (used for PostgreSQL) dependencies
gem install rails -v "5.2.0"- installs Rails
rails new . --database=postgresql- bootstraps Rails application using Postgres as default DB. Finally!
Interactive rails new
If you want to experiment with
rails new parameters you can use an interactive shell instead.
docker run --rm -it -v $PWD:/app -w /app ruby:2.5.1-alpine /bin/sh
Please notice new docker option:
-it. These are two separate options:
--tty). Usually you want to use them together when running anything interactive.
Custom application name
rails new required
PATH argument not only determines the path but also is used to set the application name.
The app name is used in
config/application.rb to define a top module.
Unfortunately for some reason it’s not possible to provide application name as an option.
To work around this issue use custom volume mountpoint and absolute path of current directory instead of
docker run --rm -v $PWD:/$(basename $PWD) -w /$(basename $PWD) ruby:2.5.1-alpine /bin/sh -c 'apk add --update build-base postgresql-dev && gem install rails -v "5.2.0" && rails new $PWD --database=postgresql'
File permissions in Linux host volumes
If you are using a Linux host to run Docker all files created by
rails new are owned by root on your local machine.
The problem is fixable using
sudo chown but it’s just a temporary solution. The only permit solution is to use user namespace that will help you with remapping your host user to Docker.
My post about Linux user namespaces shows how to fix this properly.
This problem doesn’t exist on Mac OS or Windows where NFS is used to mount local volumes.