Zero to Up and Running a Rails Project only using Docker

Disclaimer: this post is based on Quickstart: Compose and Rails — Docker the main difference is that I will run everything with my own user and cache the gems installations.

First, create the directory for your project:

% mkdir ~/my-blog
% cd ~/my-blog

Now create the Dockerfile:

from ruby

env DEBIAN_FRONTEND=noninteractive \
  NODE_VERSION=6.9.1

run sed -i '/deb-src/d' /etc/apt/sources.list && \
  apt-get update && \
  apt-get install -y build-essential libsqlite3-dev sqlite3

run curl -sSL "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" | tar xfJ - -C /usr/local --strip-components=1 && \
  npm install npm -g

run useradd -m -s /bin/bash -u 1000 railsuser
user railsuser

workdir /app

And the docker-compose.yml:

version: "2"

services:
  web:
    build: .
    volumes:
      - .:/app
      - bundle_path:/bundle
    environment:
      - BUNDLE_PATH=/bundle/vendor
      - BUNDLE_APP_CONFIG=/app/.bundle
    user: railsuser
    command: bundle exec rails server
    ports:
      - "3000:3000"

volumes:
  bundle_path:

Build it:

% docker-compose build

Create the Gemfile:

source "https://rubygems.org"

gem "rails"

Install your gems:

% docker-compose run --rm -u root web bash -c "mkdir -p /bundle/vendor && chown -R railsuser /bundle/vendor"
% docker-compose run --rm web bundle install --path /bundle/vendor

Build the project:

% docker-compose run web bundle exec rails new . --force --skip-bundle

Run bundle install again:

% docker-compose run --rm web bundle install

Bonus: Change the Project to use PostgreSQL

Edit Gemfile removing the gem sqlite3 and adding pg.

Run bundle install to install the gem pg:

docker-compose run --rm web bundle install

Change the Dockerfile to use PostgreSQL:

from ruby

env DEBIAN_FRONTEND=noninteractive \
  NODE_VERSION=6.9.1

run sed -i '/deb-src/d' /etc/apt/sources.list && \
  apt-get update && \
  apt-get install -y build-essential libpq-dev postgresql-client

run curl -sSL "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" | tar xfJ - -C /usr/local --strip-components=1 && \
  npm install npm -g

run useradd -m -s /bin/bash -u 1000 railsuser
user railsuser

workdir /app

Build it again:

% docker-compose build

Change docker-compose.yml to also run PostgreSQL:

version: "2"

services:
  web:
    build: .
    volumes:
      - .:/app
      - bundle_path:/bundle
    environment:
      - BUNDLE_PATH=/bundle/vendor
      - BUNDLE_APP_CONFIG=/app/.bundle
    user: railsuser
    command: bundle exec rails server -b 0.0.0.0
    ports:
      - "3000:3000"
    links:
      - db

  db:
    image: postgres
    volumes:
      - db:/var/lib/postgresql/data
    expose:
      - '5432'

volumes:
  bundle_path:
  db:

Update the configuration for the database editing the file config/database.yml like this:

development: &default
  adapter: postgresql
  database: myblog_development
  encoding: unicode
  host: db
  username: postgres
  password:
  pool: 5

test:
  <<: *default
  database: myblog_test

production:
  <<: *default
  database: myblog_production

Create your database, migrate and/or seed it:

docker-compose run --rm web bundle exec rake db:create
docker-compose run --rm web bundle exec rake db:migrate
docker-compose run --rm web bundle exec rake db:seed

#protip: you can execute rails db:setup to run altogether.

Now your project is ready to run your app with PostgreSQL.

At last but not least important: Document your up and running process

Remember: the process is now partially automated due to the bundler cache, so everyone will need to run these commands to setup the project:

% docker-compose run --rm -u root web bash -c "mkdir -p /bundle/vendor && chown railsuser /bundle/vendor"
% docker-compose run --rm web bundle install

And, of course:

% docker-compose run --rm web bundle exec rake db:setup

And to run:

% docker-compose up web

You can create a README like this:

# My Blog

## Running

Setup:

    % docker-compose run --rm -u root web bash -c "mkdir -p /bundle/vendor && chown railsuser /bundle/vendor"
    % docker-compose run --rm web bundle install
    % docker-compose run --rm web bundle exec rake db:setup

Run:

    % docker-compose up web

And go to [localhost:3000](http://localhost:3000).

Or even a bin/setup:

#!/bin/bash

set -xe

# Uncomment this line and ensure your config/database.yml.sample is ready to run with docker.
# cp config/database.yml.sample config/database.yml

docker-compose run --rm -u root web bash -c "mkdir -p /bundle/vendor && chown railsuser /bundle/vendor"
docker-compose run --rm web bundle install
docker-compose run --rm web bundle exec rake db:setup

Conclusion

Like I said in How to install Docker and docker-compose I have nothing in my machine itself.

But this is only one way to solve this problem. If you know any other way to use it (or if you prefer another) please comment below 🙂

Thanks to Marina Limeira, Will Soares, and abnersajr.