Dockerize Rails Application

If you enjoy this article you may be interested in the book I am working on called Building and Deploying Crypto Trading Bots. You can find more info about it here.

I forget how to do this a lot. This is me memoizing it for myself. This is not optimal but will get you off ground zero.

Ignore node_modules in .dockerignore because the container image (Linux) is probably different from the host image (Mac). By ignoring this we avoid having messed up node dependancies by platform.

node_modules/		
.dockerignore

Add a Dockerfile

FROM ruby:2.7.0-alpine

# Update the installer
RUN apk update -qq && apk upgrade

# Install Deps
RUN apk add --no-cache \
	 # Necesssary
	 build-base \
	 postgresql-dev \
   postgresql-client \
	 nodejs yarn tzdata \
	 # Good to have 
	 vim bash git

RUN gem install bundler --version '~> 2.1.0'

# Create that directory in the base image
WORKDIR /usr/src/app

COPY . .
RUN yarn install --check-files
RUN bundle install

# App
EXPOSE 3000
Dockerfile

Then create a docker-compose.yml:

version: "3"
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    command: './entrypoint.sh'
    ports:
      - "3000:3000"
    volumes:
      - .:/app
    env_file: .env.docker
    depends_on:
      - redis
      - db
  db:
    # Use postgres image v9.6
    image: postgres:9.6
    # Access container port 5432 on host port 5432
    ports:
       - "5432:5432"
    volumes:
       # Set database volume in Rails tmp folder
       - ./tmp/db:/var/lib/postgresql/data
    environment:
       # Username to access the server
       POSTGRES_USER: rails
       # Password to access the server
       POSTGRES_PASSWORD: hunter2
       
# If you want to use redis
# redis:
#  image: redis:5.0-alpine
#  ports:
#    - '6379:6379'
#  volumes:
#   - /tmp/db:/var/lib/redis/data

# If you use Sidekiq
# sidekiq:
#  build:
#   context: .
#   dockerfile: Dockerfile
#  command: './entrypoint_sidekiq.sh'
#  volumes:
#    - .:/app
#  depends_on:
#    - redis
docker-compose.yml

Add an entrypoint.sh which is just a bash script to execute and start the rails server process:


#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /app/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
bundle exec rails s -p 3000 -b 0.0.0.0
entrypoint.sh

Have fun!