This is a generator for Rails project setup with docker, Postgres, Redis, Sidekiq; with container orchestration using docker-compose. The goal of this is to do everything in Docker including the initial project setup in order to eliminate the need to install anything locally.
- Set the
:HEADER-ARGS:
property for each file with the:tangle
path. This is where the generated file will be written. See also Using Header Arguments. - Edit the
config
Association List below. Select the desired versions and app name. - call
org-babel-tangle
to generate the files in your chosen tangle directory. - Run the setup script as an entry point to a temp container based on the
selected image. The command is generated in a
Usage
comment insetup.sh
. - Add a
.env
file - Add a
.dockerignore
. See this gist for ideas of what to ignore. TODO: just generate this, dummy. - Update
Procfile.dev
to bind the server to0.0.0.0
web: unset PORT && bin/rails server -p 3000 -b '0.0.0.0'
- Build container image
docker-compose build
- Start the app with
docker-compose up
This will run the config
elisp block below several times. Set the
org-confirm-babel-evaluate
variable to nil
to skip prompting.
(setq config
'(("ruby-version" . "3.2.2")
("node-major" . "20")
("pg-version" . "latest")
("redis-version" . "latest")
("app-name" . "tmp")))
(cdr (assoc key config))
This is a multistage docker build. The advantage is having yarn and bundle dependencies being a step that is cached independently.
ARG RUBY_VERSION=<<config("ruby-version")>>
FROM ruby:$RUBY_VERSION-slim as base
RUN apt-get update -qq \
&& apt-get install --no-install-recommends -y build-essential ca-certificates curl gnupg locales libvips libpq-dev \
libwebp-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists /var/cache/apt/archives
WORKDIR /rails
# Install Node and Yarn JS package manager
# See also https://github.com/nodesource/distributions#installation-instructions
ARG NODE_MAJOR=<<config("node-major")>>
ARG YARN_VERSION=1.22.19
RUN mkdir -p /etc/apt/keyrings && \
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_MAJOR}.x nodistro main" | \
tee /etc/apt/sources.list.d/nodesource.list && \
apt-get update && \
apt-get install nodejs -y && \
npm install -g yarn@$YARN_VERSION
# Install JS dependencies
FROM base as node
COPY package.json yarn.lock ./
RUN yarn install
# Install Ruby dependencies
FROM base as gems
COPY Gemfile Gemfile.lock ./
RUN gem install bundler && bundle install --jobs 20 --retry 5
# Final build
FROM base as build
WORKDIR /rails
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
COPY . ./
# Copy ruby and JS dependencies
COPY --from=gems /usr/local/bundle /usr/local/bundle
COPY --from=node /rails/node_modules /rails/node_modules
EXPOSE 3000
CMD ["bin/dev"]
This orchestrates the following containers:
- web
- database
- redis
- sidekiq
The sidekiq
command
is basic in this example. To specify queues for example usebundle exec sidekiq -q default -q other
. Dosidekiq --help
to see all the options.
Environment variables are provided via a .env
file in the project root. This
file is automatically generated by the setup script below.
version: "3.6"
services:
web:
tty: true
stdin_open: true
build: .
command: bash -c "rm -f tmp/pids/server.pid && /app/bin/dev"
volumes:
- ".:/app"
- "/app/node_modules" # don't mount node_modules dir
ports:
- "3000:3000"
links:
- "database"
- "redis"
env_file:
- ".env"
database:
image: postgres:<<config("pg-version")>>
volumes:
- 'postgres:/var/lib/postgresql/data'
ports:
- "5432"
env_file:
- ".env"
redis:
image: redis:<<config("redis-version")>>
volumes:
- "redis:/data"
ports:
- "6379"
sidekiq:
depends_on:
- "database"
- "redis"
build: .
volumes:
- ".:/app"
- "/app/tmp" # don't mount tmp dir
command: "bundle exec sidekiq"
env_file:
- ".env"
volumes:
redis:
postgres:
**See Usage comment in the script for how to run it**
This is a one time setup script. It can be deleted after it is run.
- This is for rails v ~>7
- See also nodesource.
# Usage:
# docker run --rm -it -v "$PWD":/app -w /app ruby:<<config("ruby-version")>> sh setup.sh
# Install dependencies
gem install rails -v "~> 7"
# Install node from nodesource
https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions
curl -fsSL https://deb.nodesource.com/setup_<<config("node-major")>>.x | bash - && apt-get install -y nodejs
# Install yarn
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 update && apt install -y yarn
# Setup rails app
rails new . --database=postgresql --javascript=esbuild --css=bootstrap --name=<<config("app-name")>>
bundle add sidekiq --skip-install
bundle add rubocop --group development --require false --skip-install
bundle add rubocop-performance --group development --require false --skip-install
bundle add rubocop-rails --group development --require false --skip-install
bundle add rubocop-rspec --group development --require false --skip-install
bundle add rspec-rails --group "development, test" --skip-install
bundle add factory_bot_rails --group "development, test"
# Configure database
DBCONFIG=$(cat <<EOF
default: &default
adapter: postgresql
encoding: unicode
host: <%= ENV['POSTGRES_HOST'] %>
user: <%= ENV['POSTGRES_USER'] %>
password: <%= ENV['POSTGRES_PASSWORD'] %>
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
development:
<<: *default
database: <<config("app-name")>>_development
test:
<<: *default
database: <<config("app-name")>>_test
production:
<<: *default
database: <<config("app-name")>>_production
username: <<config("app-name")>>
password: <%= ENV['SUPER_SECRET_DATABASE_PASSWORD'] %>
EOF
)
echo "$DBCONFIG" > config/database.yml
# Add env vars for development
touch .env
echo "POSTGRES_DB=<<config("app-name")>>_development" >> .env
echo "POSTGRES_USER=postgres" >> .env
echo "POSTGRES_PASSWORD=postgres" >> .env
echo "POSTGRES_HOST=database" >> .env
echo "PGUSER=postgres" >> .env
echo "REDIS_URL=redis://redis:6379/1" >> .env
After completing the project setup, run:
docker-compose build
to build the image
docker-compose up
to run the containers
Tear it down with:
docker-compose down
See https://github.com/apmiller108/astronomania-api README for example of more commands like debugged with pry and running tests.
This is the travis.yml
. Most of this is boiler plate from Travis’ docs. The
env stuff I had to figure out becuase I am using a .env file to pass config
vars into containers with docker-compose. First I had to add the env vars to
Travis’ project settings. Then echo them into a .env file for docker-compose
to read from.
NOTE: the COMPOSE_VERSION
is NOT the docker-compose file version, but
the docker-compose release version:
Releases · docker/compose · GitHub
NOTE: this file doesn’t get generated. Use it if you want.
language: bash
sudo: required
services:
- docker
env:
COMPOSE_VERSION: 1.26.2
before_install:
- sudo rm /usr/local/bin/docker-compose
- curl -L https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
- chmod +x docker-compose
- sudo mv docker-compose /usr/local/bin
- docker --version
- docker-compose --version
script:
- touch .env
- echo "POSTGRES_DB=${POSTGRES_DB}" >> .env
- echo "POSTGRES_USER=${POSTGRES_USER}" >> .env
- echo "POSTGRES_PASSWORD=${POSTGRES_PASSWORD}" >> .env
- echo "POSTGRES_HOST=${POSTGRES_HOST}" >> .env
- echo "NASA_API_KEY=${NASA_API_KEY}" >> .env
- docker-compose up --detach --build
- docker ps -a
- docker-compose exec web bin/rails db:schema:load RAILS_ENV=test
- docker-compose exec web bundle exec rspec
after_script:
- docker-compose down
- rm .env
notifications:
email: false
- Setup a Ruby on Rails 6 API project with Docker Compose \| Yi Zeng’s Blog
- Add Sidekiq to a Docker Compose managed Rails project \| Yi Zeng’s Blog
- [[https://learning.oreilly.com/library/view/docker-for-rails/9781680506730/f_0014.xhtml#part-development][Part I. Development - Docker for Rails Developers [Book]]]
- Compose file version 3 reference | Docker Documentation
- https://evilmartians.com/chronicles/ruby-on-whales-docker-for-ruby-rails-development