Bootstrap rails docker environment

Posted by Markus Benning on June 20, 2019

This article will show how to bootstrap a new rails application within a containerized environment.

The example will setup an API only rails application with a webpacker/react frontend, but it can also be used for setting up a regular rails application by leaving out the webpacker/react configuration.

Generate rails application

Create a new project folder:

mkdir app && cd app

Start a container with a recent ruby version:

docker run --rm -it -v "$PWD:/app" ruby:2.6 bash

Within the container install rails and create a new rails application:

gem install rails
rails new . --api --webpack=react --database=postgresql

Installation of webpack/react will fail at this stage.

Change file ownership to the uid/gid of your regular user:

chown -R 1000:1000 .

Shutdown the temporary container by exiting the shell.

Create docker image

Create the following start.sh startup script:

#!/bin/bash

# make sure to cleanup pid file
rm -f /app/tmp/pids/server.pid

bundle exec rails server -b 0.0.0.0

And the following Dockerfile:

FROM ruby:2.6
ENV BUNDLER_PATH /gems

RUN apt-get update -qq \
  && apt-get install -y curl \
  && curl -sL https://deb.nodesource.com/setup_12.x | bash - \
  && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
  && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
  && apt-get update -qq \
  && apt-get install -y nodejs yarn postgresql-client \
  && rm -rf /var/lib/apt/lists/*

RUN mkdir /app
WORKDIR /app

COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app

EXPOSE 3000

CMD ["/app/start.sh"]

Create docker-compose environment

Create the following docker-compose.yml file:

version: '3'
services:
  web:
    build: .
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - database

  database:
    image: postgres
    volumes:
      - pg_data:/var/lib/postgresql/data

  webpacker:
    build: .
    command: ./bin/webpack-dev-server
    volumes:
      - .:/app
    ports:
      - '3035:3035'
    environment:
      - "NODE_ENV=development"
      - "RAILS_ENV=development"
      - "WEBPACKER_DEV_SERVER_HOST=0.0.0.0"

volumes:
  pg_data:
    driver: local

Then build the docker image by executing:

docker-compose build

Initialize database

Configure the database connection in config/database.yml:

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: database
  username: postgres
  password: ''

development:
  <<: *default
  database: app_development

test:
  <<: *default
  database: app_test

production:
  <<: *default
  database: app_production
  username: app
  password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>

Start a shell within the web container:

docker-compose run web bash

With the container initialize the database by executing:

bundle exec rake db:create

Install webpack/react

Still being in the web container shell execute:

bundle exec rake webpacker:install
bundle exec rake webpacker:install:react

Shutdown the web container by exiting the shell.

Start up application environment

Startup container environment by executing:

docker-compose up

Then point your browser to your rails application at:

http://localhost:3000

Or to the webpacker development server at:

http://localhost:3035