Setup Rails API with Docker Compose
- Maciej Biel
- 3 November 2022
Update Notice - 01.2023 :
This article is outdated and shows bad practises about creating Docker images. Check out improved version of this article here.
The most important thing when dealing with Rails is to use Linux, it’s a must! Also keep in mind that installing Rails is tricky and sometimes it can drive you crazy. Lets get straight into configuration.
In this configuration, a volume with Rails project inside the container is mapped to a directory with project on the local system. The only problem is with executables like Rubocop
, so I use Visual Studio with Dev Containers
extension and I can attach directly to container to make executables works.
If you are ready, open terminal and type the following commands:
mkdir <project-name>
cd <project-name>
touch Dockerfile
touch entrypoint.sh
touch docker-compose.yml
touch .dockerignore
touch .env
touch Gemfile
touch Gemfile.lock
Files listed below should have the following content:
.env
RUBY_VERSION=3.1.0
RAILS_USER=rails-user
GEM_HOME=/home/${RAILS_USER}/.gem/${RUBY_VERSION}
POSTGRES_HOST=db
POSTGRES_PORT=5432
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=postgres
docker-compose.yml
version: "3"
services:
db:
image: postgres:13
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
env_file:
- ".env"
rails:
build:
context: .
args:
- RUBY_VERSION=$RUBY_VERSION
- RAILS_USER=$RAILS_USER
- GEM_HOME=$GEM_HOME
volumes:
- .:/app
- gems:$GEM_HOME
ports:
- "3000:3000"
command: rails server -p 3000 -b '0.0.0.0'
depends_on:
- db
env_file:
- ".env"
volumes:
pgdata:
gems:
Dockerfile
ARG RUBY_VERSION
FROM ruby:$RUBY_VERSION-alpine
ARG RAILS_USER
ENV RAILS_ROOT /app
ARG GEM_HOME
ENV LANG C.UTF-8
RUN apk add --update --no-cache \
build-base \
postgresql-dev \
tzdata \
sudo \
git
RUN adduser -D $RAILS_USER
RUN mkdir -p $RAILS_ROOT \
chown $RAILS_USER $RAILS_ROOT
WORKDIR $RAILS_ROOT
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
USER $RAILS_USER
COPY --chown=$RAILS_USER Gemfile Gemfile.lock ./
RUN echo "gem: --user-install --env-shebang --no-rdoc --no-ri" > /home/$RAILS_USER/.gemrc
ENV GEM_HOME $GEM_HOME
ENV PATH $GEM_HOME/bin:$PATH
RUN bundle install
COPY --chown=$RAILS_USER . .
EXPOSE 3000
entrypoint.sh
#!/bin/sh
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f $RAILS_ROOT/tmp/pids/server.pid
exec "$@"
Gemfile.lock
- should be empty
Gemfile
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "rails", "~> 7.0.3"
I assume you’ve already installed Docker on your machine (use docker command without prefacing with sudo every time).
Now, let’s build docker image. Run the following command:
docker compose build
You should only type this one command below if you are setting up project for first time!
It creates new Rails API project inside container and installs it:
docker compose run --rm rails rails new . --force --api --database=postgresql --skip-test --skip-spring --skip-coffee
If installation went fine, we can move on to configuring database inside Rails project. Edit that code fragment inside volume in config/database.yml
:
default: &default
adapter: postgresql
encoding: unicode
host: <%= ENV['POSTGRES_HOST'] %>
port: <%= ENV['POSTGRES_PORT'] %>
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: <%= ENV['POSTGRES_USERNAME'] %>
password: <%= ENV['POSTGRES_PASSWORD'] %>
Now run both Postgres and Rails using docker compose:
docker compose up
Application isn’t working yet, because we have to setup database and apply migrations. To access Rails container type in terminal:
docker compose exec rails sh
When we have direct access to rails
executable, type:
rails db:setup
If everyting works, you are ready to start working on your project.