Skip to content

Commit

Permalink
feat: docker for development
Browse files Browse the repository at this point in the history
  • Loading branch information
palkan committed Apr 28, 2023
1 parent 53235ee commit cb89efc
Show file tree
Hide file tree
Showing 13 changed files with 558 additions and 66 deletions.
1 change: 1 addition & 0 deletions .dockerdev/.bashrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
alias be="bundle exec"
26 changes: 26 additions & 0 deletions .dockerdev/.psqlrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
-- Don't display the "helpful" message on startup.
\set QUIET 1

-- Allow specifying the path to history file via `PSQL_HISTFILE` env variable
-- (and fallback to the default $HOME/.psql_history otherwise)
\set HISTFILE `[ -z $PSQL_HISTFILE ] && echo $HOME/.psql_history || echo $PSQL_HISTFILE`

-- Show how long each query takes to execute
\timing

-- Use best available output format
\x auto

-- Verbose error reports
\set VERBOSITY verbose

-- If a command is run more than once in a row,
-- only store it once in the history
\set HISTCONTROL ignoredups
\set COMP_KEYWORD_CASE upper

-- By default, NULL displays as an empty space. Is it actually an empty
-- string, or is it null? This makes that distinction visible
\pset null '[NULL]'

\unset QUIET
3 changes: 3 additions & 0 deletions .dockerdev/Aptfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# We might need an editor to work with credentials
vim
libicu-dev
85 changes: 85 additions & 0 deletions .dockerdev/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# syntax=docker/dockerfile:1

ARG RUBY_VERSION
ARG DISTRO_NAME=bullseye

FROM ruby:$RUBY_VERSION-slim-$DISTRO_NAME

ARG DISTRO_NAME

# Common dependencies
# Using --mount to speed up build with caching, see https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/reference.md#run---mount
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=tmpfs,target=/var/log \
rm -f /etc/apt/apt.conf.d/docker-clean; \
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache; \
apt-get update -qq && \
DEBIAN_FRONTEND=noninteractive apt-get -yq dist-upgrade && \
DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
build-essential \
gnupg2 \
curl \
less \
git

ARG PG_MAJOR
RUN curl -sSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /usr/share/keyrings/postgres-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/postgres-archive-keyring.gpg] https://apt.postgresql.org/pub/repos/apt/" \
$DISTRO_NAME-pgdg main $PG_MAJOR | tee /etc/apt/sources.list.d/postgres.list > /dev/null
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=tmpfs,target=/var/log \
apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get -yq dist-upgrade && \
DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
libpq-dev \
postgresql-client-$PG_MAJOR

ARG NODE_MAJOR
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=tmpfs,target=/var/log \
curl -sL https://deb.nodesource.com/setup_$NODE_MAJOR.x | bash - && \
DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
nodejs

ARG YARN_VERSION
RUN npm install -g yarn@$YARN_VERSION

# Application dependencies
# We use an external Aptfile for this, stay tuned
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=tmpfs,target=/var/log \
--mount=type=bind,source=Aptfile,target=/tmp/Aptfile \
DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
$(grep -Ev '^\s*#' /tmp/Aptfile | xargs)

# Install Hivemind to run frontend builders in a single container
RUN arch=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) && \
curl -L "https://github.com/DarthSim/hivemind/releases/download/v1.1.0/hivemind-v1.1.0-linux-${arch}.gz" | gunzip > /usr/local/bin/hivemind && \
chmod +x /usr/local/bin/hivemind

# Configure bundler
ENV LANG=C.UTF-8 \
BUNDLE_JOBS=4 \
BUNDLE_RETRY=3

# Store Bundler settings in the project's root
ENV BUNDLE_APP_CONFIG=.bundle

# Uncomment this line if you want to run binstubs without prefixing with `bin/` or `bundle exec`
# ENV PATH /app/bin:$PATH

# Upgrade RubyGems and install the latest Bundler version
RUN gem update --system && \
gem install bundler

# Create a directory for the app code
RUN mkdir -p /app
WORKDIR /app

# Document that we're going to expose port 3000
EXPOSE 3000
# Use Bash as the default command
CMD ["/usr/bin/bash"]
4 changes: 4 additions & 0 deletions .dockerdev/Procfile.frontend
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
js: yarn build --watch
light-js: yarn light:build --watch
light-css: yarn light:build:css --watch
light-mailer-css: yarn light:build:mailer:css --watch
78 changes: 78 additions & 0 deletions .dockerdev/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Docker for Development

Source: [Ruby on Whales: Dockerizing Ruby and Rails development](https://evilmartians.com/chronicles/ruby-on-whales-docker-for-ruby-rails-development).

## Installation

- Docker installed.

For MacOS just use the [official app](https://docs.docker.com/engine/installation/mac/).

- [`dip`](https://github.com/bibendi/dip) installed.

You can install `dip` as Ruby gem:

```sh
gem install dip
```

## Provisioning

When using Dip it could be done with a single command:

```sh
dip provision
```

## Running

```sh
dip rails s
```

## Developing with Dip

### Useful commands

```sh
# run rails console
dip rails c

# run rails server with debugging capabilities (i.e., `debugger` would work)
dip rails s

# or run the while web app (with all the dependencies)
dip up web

# run migrations
dip rails db:migrate

# pass env variables into application
dip VERSION=20100905201547 rails db:migrate:down

# run super scaffolding
dip super-scaffold

# simply launch bash within app directory (with dependencies up)
dip runner

# execute an arbitrary command via Bash
dip bash -c 'ls -al tmp/cache'

# Additional commands

# update gems or packages
dip bundle install

# run psql console
dip psql

# run tests
dip rails test

# run system tests
dip rails test:system

# shutdown all containers
dip down
```
146 changes: 146 additions & 0 deletions .dockerdev/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
x-app: &app
build:
context: .
args:
RUBY_VERSION: '3.2.1'
PG_MAJOR: '14'
NODE_MAJOR: '19'
YARN_VERSION: '1.22.19'
image: untitled-application-dev:1.0.0
environment: &env
NODE_ENV: ${NODE_ENV:-development}
RAILS_ENV: ${RAILS_ENV:-development}
BULLET_TRAIN_ENV: "docker"
tmpfs:
- /tmp
- /app/tmp/pids

x-backend: &backend
<<: *app
stdin_open: true
tty: true
volumes:
- ..:/app:cached
- bundle:/usr/local/bundle
- rails_cache:/app/tmp/cache
- node_modules:/app/node_modules
- assets:/app/public/assets
- assets_builds:/app/app/assets/builds
- history:/usr/local/hist
- ./.psqlrc:/root/.psqlrc:ro
- ./.bashrc:/root/.bashrc:ro
environment: &backend_environment
<<: *env
REDIS_URL: redis://redis:6379/
DATABASE_URL: postgres://postgres:postgres@postgres:5432
REMOTE_CHROME_URL: ${REMOTE_CHROME_URL:-http://chrome:3333}
MALLOC_ARENA_MAX: 2
WEB_CONCURRENCY: ${WEB_CONCURRENCY:-1}
BOOTSNAP_CACHE_DIR: /usr/local/bundle/_bootsnap
XDG_DATA_HOME: /app/tmp/cache
YARN_CACHE_FOLDER: /app/node_modules/.yarn-cache
HISTFILE: /usr/local/hist/.bash_history
PSQL_HISTFILE: /usr/local/hist/.psql_history
IRB_HISTFILE: /usr/local/hist/.irb_history
EDITOR: vi
depends_on: &backend_depends_on
postgres:
condition: service_healthy
redis:
condition: service_healthy

services:
rails:
<<: *backend
command: bundle exec rails

web:
<<: *backend
command: bundle exec rails server -b 0.0.0.0
ports:
- '3000:3000'
depends_on:
frontend:
condition: service_started
sidekiq:
condition: service_started

# Special service definition for system tests
# which launches Chrome service in addition to other deps
rails_chrome:
<<: *backend
environment:
<<: *backend_environment
APP_HOST: ${APP_HOST:-http://untitled-application.test:3001}
ports:
- '3001:3001'
depends_on:
<<: *backend_depends_on
chrome:
condition: service_started
networks:
default:
aliases:
- untitled-application.test

sidekiq:
<<: *backend
command: bundle exec sidekiq

frontend:
<<: *backend
command: hivemind --root=./ .dockerdev/Procfile.frontend

postgres:
image: postgres:14
volumes:
- .psqlrc:/root/.psqlrc:ro
- postgres:/var/lib/postgresql/data
- history:/user/local/hist
environment:
PSQL_HISTFILE: /user/local/hist/.psql_history
POSTGRES_PASSWORD: postgres
ports:
- 5432
healthcheck:
test: pg_isready -U postgres -h 127.0.0.1
interval: 5s

redis:
image: redis:6.2-alpine
volumes:
- redis:/data
ports:
- 6379
healthcheck:
test: redis-cli ping
interval: 1s
timeout: 3s
retries: 30

chrome:
# See https://github.com/browserless/chrome/issues/1393
image: browserless/chrome:latest
ports:
- "3333:3333"
# Mount application source code to support file uploading
# (otherwise Chrome won't be able to find files).
# NOTE: Make sure you use absolute paths in `#attach_file`.
volumes:
- ..:/app:cached
environment:
# By default, it uses 3000, which is typically used by Rails.
PORT: 3333
# Set connection timeout to avoid timeout exception during debugging
# https://docs.browserless.io/docs/docker.html#connection-timeout
CONNECTION_TIMEOUT: 600000

volumes:
bundle:
node_modules:
history:
rails_cache:
postgres:
redis:
assets:
assets_builds:
Loading

0 comments on commit cb89efc

Please sign in to comment.