Skip to content

Instantly share code, notes, and snippets.

@jgarber623
Last active January 27, 2023 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jgarber623/93af55a1091261bf13609802d40c0cd8 to your computer and use it in GitHub Desktop.
Save jgarber623/93af55a1091261bf13609802d40c0cd8 to your computer and use it in GitHub Desktop.
A set of files that could serve as a starting point for a Docker-based Ruby on Rails application.
services:
app:
# Assumes this image is available on Docker Hub. If it's not, you'd want to add this
# config:
#
# build:
# context: .
#
# @see https://docs.docker.com/compose/compose-file/#build
image: jgarber623/thing-app
# Instructs `docker compose up` to pull the latest version of the image defined above.
# May or may not be desirable, depending on the circumstance. Could also be achieved
# by running:
#
# bin/start --pull always
#
# @see https://docs.docker.com/compose/compose-file/#pull_policy
pull_policy: always
container_name: thing-app
# Initialize these services before the `app` service. Shutdown occurs in reverse
# order. The degree to which this is necessary depends on the app's requirements,
# of course.
depends_on:
- db
- redis
# Equivalent to passing the `--init` flag to `docker run`. Dramatically speeds up
# container shutdown.
#
# @see https://docs.docker.com/compose/compose-file/#init
init: true
# Adding an entrypoint script so we can output helpful information to the user
# when invoking `bin/start`.
entrypoint: ./docker-entrypoint.sh
ports:
- "3000:3000"
volumes:
- type: bind
source: .
target: /usr/src/app
consistency: delegated
- type: volume
target: /usr/src/dependencies
db:
image: postgres:14-alpine
container_name: thing-db
environment:
POSTGRES_PASSWORD: postgres
redis:
image: redis:7-alpine
container_name: thing-redis
# Docker automatically defines and names networks somewhat randomly, so we instead
# specify a name for the network used by the services above. If you ever need to
# access details about the network, you'll know its name.
networks:
default:
name: thing-network
#!/usr/bin/env sh
set -e
# Output some helpful messaging when invoking `bin/start` (which itself is
# a convenience script for `docker compose up`.
#
# Adding this to work around the mild inconvenience of the `app` container's
# entrypoint generating no output.
#
cat <<-'PROMPT'
🤖 thing-app container initialized!
To continue, run the following command in a new Terminal tab:
bin/exec bin/run
Use `ctrl-c` to exit.
PROMPT
# Using `sleep infinity` instead of `tail -f /dev/null`. This may be a
# performance improvement based on the conversation on a semi-related
# StackOverflow page.
#
# @see https://stackoverflow.com/a/41655546
sleep infinity
FROM debian:bullseye-slim
ARG NODE_VERSION="18.x"
ARG POSTGRESQL_VERSION="14"
ARG RAILS_VERSION=">= 7.0"
ARG REDIS_VERSION="7.0.5"
ARG RUBY_INSTALLER_VERSION="0.8.5"
ARG RUBY_VERSION="3.1.2"
ENV DEBIAN_FRONTEND=noninteractive
# Install system dependencies.
RUN apt update --quiet && \
apt install --quiet --yes \
bison \
build-essential \
g++ \
git \
gnupg2 \
less \
libffi-dev \
libgdbm-dev \
libncurses5-dev \
libreadline-dev \
libssl-dev \
libyaml-dev \
locales \
lsb-release \
make \
tzdata \
wget \
zlib1g-dev
# Install PostgreSQL development and client libraries.
# See: https://wiki.postgresql.org/wiki/Apt
RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/apt.postgresql.org.gpg > /dev/null && \
echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \
apt update --quiet && \
apt install --quiet --yes \
libpq-dev \
postgresql-client-${POSTGRESQL_VERSION}
# Install redis-cli the hard way.
RUN wget https://download.redis.io/releases/redis-${REDIS_VERSION}.tar.gz && \
tar -xzvf redis-${REDIS_VERSION}.tar.gz && \
make -C redis-${REDIS_VERSION} install redis-cli /usr/local/bin && \
rm -rf redis-${REDIS_VERSION}*
# Create a folder to use as a persistent volume for caching dependencies.
RUN mkdir -p /usr/src/dependencies
# Download, verify, and install ruby-install
# See: https://github.com/postmodern/ruby-install
RUN wget -O ruby-install-${RUBY_INSTALLER_VERSION}.tar.gz https://github.com/postmodern/ruby-install/archive/v${RUBY_INSTALLER_VERSION}.tar.gz && \
wget --quiet -O - https://raw.github.com/postmodern/postmodern.github.io/main/postmodern.asc | gpg --import && \
wget https://raw.github.com/postmodern/ruby-install/master/pkg/ruby-install-${RUBY_INSTALLER_VERSION}.tar.gz.asc && \
gpg --verify ruby-install-${RUBY_INSTALLER_VERSION}.tar.gz.asc ruby-install-${RUBY_INSTALLER_VERSION}.tar.gz && \
tar -xzvf ruby-install-${RUBY_INSTALLER_VERSION}.tar.gz && \
make -C ruby-install-${RUBY_INSTALLER_VERSION} install && \
rm -rf ruby-install-${RUBY_INSTALLER_VERSION}*
# Install the version of Ruby defined at the top of this file.
RUN ruby-install --system ruby ${RUBY_VERSION}
# Silence Ruby deprecation warnings.
ENV RUBYOPT=-W:no-deprecated
# Install Bundler and configure it to use the persistent volume.
RUN gem install bundler && \
bundle config path /usr/src/dependencies/bundler
# Install Node.js, enable the Yarn package manager, and configure Yarn to use
# the persistent volume..
# See: https://github.com/nodesource/distributions
RUN wget -O - https://deb.nodesource.com/setup_${NODE_VERSION} | bash - && \
apt install --quiet --yes nodejs && \
corepack enable && \
yarn config set cache-folder /usr/src/dependencies/yarn
# Configure the American English locale and use UTF-8 encoding.
RUN localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
ENV LANG=en_US.utf8
# Configure RubyGems to not install documentation, install the Foreman gem, and
# install the version of Rails specified at the top of this file.
RUN echo "gem: --no-document" >> ~/.gemrc && \
gem install foreman && \
gem install rails --version "${RAILS_VERSION}"
VOLUME /usr/src/dependencies
WORKDIR /usr/src/app
EXPOSE 3000
#!/usr/bin/env sh
# Rename this file to `bin/exec` and `chmod +x` it.
set -e
cmd=$*
container_name="jgarber623/thing-app"
container_id=$(docker ps --no-trunc --filter ancestor=${container_name} --format {{.ID}})
if [ -z "$cmd" ]; then
echo "[ bin/exec ] 🚨 No command specified!"
exit 1
fi
if [ -z $container_id ]; then
echo "[ bin/exec ] 🚨 Couldn't find a container named \"$container_name.\" Have you run \"bin/start\" in another Terminal?"
exit 1
else
echo "[ bin/exec ] 🤖 Executing command \"$cmd\" inside container with ID = $container_id..."
docker exec -it $container_id $cmd
fi
#!/usr/bin/env sh
# Rename this file to `bin/start` and `chmod +x` it.
set -e
echo "[ bin/start ] 🐳 Running ./docker-compose.yml..."
# Forward arguments passed to this script. For example:
#
# bin/start --build
#
docker compose up $@
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment