Guía de inicio para Ruby on Rails en Docker

Publicado el

Esta es una guía sencilla para iniciar un proyecto de Ruby on Rails en Docker. No para migrar un proyecto existente, aunque puede servir de base.

Lo primero es crear los ficheros Dockerfile y docker-compose.yml con el siguiente contenido:

# Dockerfile

FROM ruby:3

RUN apt-get update -qq && apt-get install -y build-essential

# for postgres
RUN apt-get install -y libpq-dev

# for a js runtime
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
RUN apt-get install -y nodejs
RUN npm install --global yarn

ENV APP_HOME /myapp
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

ENV BUNDLE_GEMFILE=$APP_HOME/Gemfile \
    BUNDLE_PATH=/bundle

ADD . $APP_HOME
# docker-compose.yml

services:
  db:
    image: postgres:13-alpine
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password

  redis:
    image: redis:alpine

  web:
    build: .
    volumes:
      - .:/myapp
      - bundler_cache:/bundle
    ports:
      - "3000:3000"
    environment:
      POSTGRES_HOST: db
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    depends_on:
      - db
      - redis

volumes:
  bundler_cache:

Entra dentro del contenedor ejecutando $ docker-compose run --rm web bash y ejecuta $ bundle init para generar el Gemfile. Dentro del Gemfile añade gem "rails" y ejecuta $ bundle install para instalar Ruby on Rails.

Una vez instalado Rails hay que iniciar el nuevo proyecto. Para eso ejecuta $ bundle exec rails new -d=postgresql ..

Tardará un rato en descargar todas las gemas e instalar los paquetes de npm. Una vez instalado hay que modificar el fichero config/database.yml para que coja los datos de la base de datos que seteamos en el docker-compose.yml.

# config/database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("POSTGRES_USER", 'postgres') %>
  password: <%= ENV.fetch("POSTGRES_PASSWORD", 'password') %>
  host: <%= ENV.fetch("POSTGRES_HOST", 'localhost') %>

Para crear la base de datos ejecuta $ ./bin/rails db:create dentro del contenedor.

Ahora que ya está el proyecto iniciado hay que modificar el Dockerfile y el docker-compose.yml. El primero para que si queremos arrancar el proyecto de cero se instalen todas las dependencias. El segundo para añadir el comando que se ejecutará al levantar Docker para arrancar Rails.

# Dockerfile

FROM ruby:3

RUN apt-get update -qq && apt-get install -y build-essential

# for postgres
RUN apt-get install -y libpq-dev

# for a js runtime
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
RUN apt-get install -y nodejs
RUN npm install --global yarn

ENV APP_HOME /myapp
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

ADD Gemfile* $APP_HOME/

ENV BUNDLE_GEMFILE=$APP_HOME/Gemfile \
    BUNDLE_PATH=/bundle

RUN gem install bundler
RUN bundle install
RUN yarn

ADD . $APP_HOME
# docker-compose.yml

services:
  db:
    image: postgres:13-alpine
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password

  redis:
    image: redis:alpine

  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bin/rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
      - bundler_cache:/bundle
    ports:
      - "3000:3000"
    environment:
      POSTGRES_HOST: db
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    depends_on:
      - db
      - redis

volumes:
  bundler_cache:

Para arrancar el proyecto solo hace falta ejecutar $ docker-compose up.

Y con esto tenemos una instalación limpia de Rails corriendo en Docker.