Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Dev Containers Docker Development Environment #203

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .devcontainer/.psqlrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
-- 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]'

\encoding unicode
\set PROMPT1 '%n@%M:%>%x %/# '
\set PROMPT2 ''

\setenv PAGER 'less -S'

\unset QUIET
44 changes: 44 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# See here for image contents: https://github.com/devcontainers/images/blob/main/src/ruby/.devcontainer/Dockerfile

# [Choice] Ruby version (use -bookworm variants on local arm64/Apple Silicon): 3, 3.2, 3.1, 3.0, 3-bookworm, 3.2-bookworm, 3.1-bookworm, 3-bullseye, 3.2-bullseye, 3.1-bullseye, 3.0-bullseye, 3-buster, 3.2-buster 3.1-buster, 3.0-buster
ARG RUBY_VERSION=3
FROM mcr.microsoft.com/devcontainers/ruby:${RUBY_VERSION}-bookworm

# borrowed some ideas from https://github.com/evilmartians/ruby-on-whales
# LABEL maintainer="Name <[email protected]>"

SHELL ["/bin/bash", "-eo", "pipefail", "-c"]

# Add PostgreSQL APT repository
RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
RUN echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list

COPY ../Aptfile.dev /tmp/Aptfile.dev
RUN apt-get update -qq && export DEBIAN_FRONTEND=noninteractive \
&& grep -Ev "^ *#" /tmp/Aptfile.dev | xargs apt-get install --no-install-recommends -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# Set the app working directory
WORKDIR /app

# Add the Rails main Gemfile and install the gems. This means the gem install can be done
# during build instead of on start. When a fork or branch has different gems, we still have an
# advantage due to caching of the other gems.
COPY Gemfile* ./
RUN bundle config set --global without "production" \
&& bundle install \
&& chown -R vscode:vscode /app /usr/local/rvm

# Run binstubs without prefixing with `bin/` or `bundle exec`
ENV PATH /app/bin:$PATH

# Expose port 3000 to the Docker host
EXPOSE 3000

# Ensure binding is always 0.0.0.0
# Binds the server to all IP addresses of the container, so it can be accessed from outside the container.
ENV BINDING="0.0.0.0"

# Start the Rails server
CMD ["bundle", "exec", "bin/rails", "server"]
77 changes: 77 additions & 0 deletions .devcontainer/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: rideshare_devcontainer

x-env: &default-env
RAILS_ENV: ${RAILS_ENV:-development}
RACK_ENV: ${RACK_ENV:-development}
WEB_CONCURRENCY: ${WEB_CONCURRENCY:-1}
RAILS_MIN_THREADS: ${RAILS_MIN_THREADS:-2}
RAILS_MAX_THREADS: ${RAILS_MAX_THREADS:-3}
MALLOC_ARENA_MAX: ${MALLOC_ARENA_MAX:-2}

x-app: &app
image: rideshare_app:0.0.1
user: "vscode"
tty: true
stdin_open: true
build:
context: ..
dockerfile: .devcontainer/Dockerfile
args:
RUBY_VERSION: ${RUBY_VERSION:-3.2}
networks:
- default
volumes:
- ../:/app:cached
- ../log:/app/log:rw,delegated
- bundle_data:/usr/local/rvm
tmpfs:
- /app/tmp:mode=01777
environment: &app-env
<<: *default-env
BIND: 0.0.0.0
DATABASE_URL: postgres://${POSTGRES_USER:-owner}:${POSTGRES_PASSWORD:-postgres}@postgres:5432
HISTFILE: /app/log/.sh_history
SOURCE_PATH: $PWD

networks:
default:

volumes:
bundle_data:
name: rideshare_bundle_data
postgres_data:
name: rideshare_postgres_data

services:
app:
<<: *app
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity
ports:
- "127.0.0.1:3000:3000"
environment:
<<: *app-env
depends_on:
- postgres

postgres:
image: postgres:${POSTGRES_VERSION:-16}
restart: unless-stopped
healthcheck:
test: pg_isready -U ${POSTGRES_USER:-postgres} -h postgres
interval: 30s
timeout: 3s
retries: 3
networks:
- default
ports:
- "127.0.0.1:5432:5432"
volumes:
- ../.devcontainer/.psqlrc:/root/.psqlrc:ro
- ../log:/var/log/postgresql:rw,delegated
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
HISTFILE: /root/log/.bash_history
PSQL_HISTFILE: /root/log/.psql_history
30 changes: 30 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/ruby
{
"name": "rideshare",
"dockerComposeFile": "compose.yaml",
"service": "app",
"workspaceFolder": "/app",
"onCreateCommand": "git config --global --add safe.directory /app",
// Configure tool-specific properties.
"containerEnv": {
"PGHOST": "postgres",
"PGUSER": "owner",
"PGPASSWORD": "postgres",
"PGDATABASE": "rideshare_development",
"RIDESHARE_DB_PASSWORD": "postgres",
"DB_URL": "postgres://postgres:postgres@postgres:5432/postgres"
},
"customizations": {
"codespaces": {
"openFiles": [
"README.md"
]
},
"vscode": {
"extensions": [
"Shopify.ruby-lsp"
]
}
}
}
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

/.devcontainer

/doc
/docs
/vendore/bundle
7 changes: 7 additions & 0 deletions Aptfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# PostgreSQL
libpq-dev
postgresql-client-16
postgresql-contrib

# Additional packages
graphviz
63 changes: 63 additions & 0 deletions docs/development_environment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Development Environment

This guide provides an alternative, community-submitted method for setting up and running the Rideshare application using Dev Containers. It is not the officially supported method described in the book "High Performance PostgreSQL for Rails."

## Get started with Docker

[Docker](https://docs.docker.com/) provides a way to run applications securely isolated in a container,
packaged with all its dependencies and libraries.

Set up your [Docker environment](https://docs.docker.com/get-started/) and run:

```bash
docker --version
docker compose --version
```

## Run Services in Docker Environment

A [Docker Compose](https://docs.docker.com/compose/compose-file/) defines all services in `.devcontainer/compose.yaml` for this app.
In order to run all servies:

```bash
docker compose -f .devcontainer/compose.yaml up -d
```

## Dev Containers

The application is configured with [devcontainers](https://code.visualstudio.com/docs/devcontainers/containers).

[A development container](https://containers.dev/overview) defines an environment
in which you develop your application before you are ready to deploy.

A `devcontainer.json` file in your project tells
[tools and services that support the dev container spec](https://containers.dev/supporting)
how to access (or create) a dev container with a well-defined tool and runtime stack.

### Install Dev Containers CLI (optional)

[This CLI](https://containers.dev/implementors/reference/) can take a `devcontainer.json` and create and configure
a dev container from it.

```bash
brew install devcontainer
```

### Build and Run Dev Container

```bash
devcontainer build --workspace-folder .
devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . db/setup.sh
```

### Run Rails Commands in Dev Containers

```bash
devcontainer exec --workspace-folder . bin/rails console
# or
$ devcontainer exec --workspace-folder . zsh
/app $ bin/rails console
```

When finish work, exit the workspace and run `docker stop $(docker container ls -q)`.