Ruby on Rails

Setup

My current Ruby setup runs these services:

app

A Ruby development server, with a local source directory added as bind mount. It runs a Puma web server, and a Sidekiq server for background jobs, such as sending emails.

db

A Postgres server, with its database stored on a Docker volume.

redis

A Redis server.

pgadmin

A PgAdmin server, to manage the Postgres database(s).

mailcatcher

A mail host to inspect emails that are sent in the current session.

chrome

A Chrome server to run headless Selenium tests.

Diagram

Configuration remarks:

The local directory is added via a bind mount, but nothing has been done yet to test how files uploaded to the server are handled.

  • The app server will be built within the container. My local machine has no Ruby or Yarn installed.

  • This creates a problem with providing an updated Gemfile.lock or yarn.lock, or having up to date node_modules. My workaround is to run a bash shell in the container, with a bind of my local directory, to install new a Gem or NPM package.

  • Some of the Gems come from private GitHub repositories. It is therefore necessary to pass an access token, using Docker secrets, and to supply them to bundle as environment variable.

  • It appears that the Ruby server does not do a lookup of localhost, and so the setting extra_hosts: localhost:host-gateway in docker-compose.yml has no effect. Instead, we add host: redis to config/redis.yml.

Example files

.env
# Postgres database
POSTGRES_USER=myusername
POSTGRES_PASSWORD=mysecretpassword
POSTGRES_DB=mydatabase

# Access to the PgAdmin server (then connect to the database)
PGADMIN_DEFAULT_EMAIL=user@domain.com
PGADMIN_DEFAULT_PASSWORD=password

# Available ports to connect to services inside the project
APP_PORT=3000
POSTGRES_PORT=35432
PGADMIN_PORT=8080
REDIS_PORT=36379
MAILCATCHER_PORT=31080

# Secrets to download private repositories from GitHub
GITHUB_TOKEN=...personal access token...
GITHUB_USER=username

RUBY_DEBUG_PORT=1234
Procfile.dev
# Run the web app with the debugger enabled (1)
web: RUBY_DEBUG_OPEN=true bin/rails s -p ${APP_PORT} -b 0.0.0.0
# js: yarn build
css: yarn build:css --watch
worker: bundle exec sidekiq
1 In VS Code, with the Dev Containers extension, it is possible to connect to the debugger. I have not found a way in RubyMine yet.
docker-compose.yml
version: '3.9'

services:
  db:
    image: postgres:13.4
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    ports:
      - "${POSTGRES_PORT}:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data

  redis:
    image: redis
    ports:
      - "${REDIS_PORT}:6379"

  app:
    build:
      context: .
      secrets:
        - github_user
        - github_token
    environment:
      DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db/${POSTGRES_DB}
      SELENIUM_HUB_URL: http://chrome:4444/wd/hub
      TEST_APP_HOST: app
      TEST_APP_PORT: 3001
    ports:
      - "${APP_PORT}:3000"
    volumes:
      - .:/app
    depends_on:
      - db
      - redis

  pgadmin:
    image: dpage/pgadmin4
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
    ports:
      - "${PGADMIN_PORT}:80"
    depends_on:
      - db

  chrome:
    image: selenium/standalone-chrome
    environment:
      HUB_HOST: hub
    ports:
      - "4444:4444"

  mailcatcher:
    image: dockage/mailcatcher
    ports:
      - "${MAILCATCHER_PORT}:1080"

volumes:
  postgres-data:

secrets:
  github_user:
    environment: "GITHUB_USER"
  github_token:
    environment: "GITHUB_TOKEN"
Dockerfile
FROM ruby:3.2

RUN curl -sL https://deb.nodesource.com/setup_18.x | bash -
RUN curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y nodejs yarn libpq-dev postgresql-client ruby-full
RUN mkdir /app

WORKDIR /app

RUN gem install rails

COPY Gemfile Gemfile.lock ./
RUN --mount=type=secret,id=github_user \
  --mount=type=secret,id=github_token \
  BUNDLE_GITHUB__COM=$(cat /run/secrets/github_user):$(cat /run/secrets/github_token) bundle install
COPY package.json yarn.lock ./
RUN yarn

# Copy the rest of the application code into the container
#COPY . .

# Precompile the assets
# RUN rails assets:precompile

EXPOSE 3000
CMD ["bin/dev"]
chevron_left
chevron_right
Twitter LinkedIn Github Gitlab Meetup RSS Miro Trello Zotero Hypothesis