【Rails】Dockerを使用してRuby on Railsの開発環境を構築

はじめに

Ruby on Railsは強力なWebアプリケーションフレームワークですが、開発環境の構築には時間がかかることがあります。特に、チーム全体で一貫した環境を維持することは困難な場合があります。

Dockerを使用することで、Ruby on Railsの開発環境を簡単に構築し、チーム全体で一貫性のある環境を維持することができます。

本記事では、Dockerを使ってRuby on Railsの開発環境を構築する方法を解説します。初心者の方でも理解しやすいよう、各ステップの詳細な説明と、そのステップが必要な理由を併せて紹介していきます。

Dockerのインストール

Docker Desktopをインストールします。

Dockerを使用するときはDocker Desktopを常に起動しておく必要があります。

Docker環境構築

ディレクトリの作成

プロジェクトのディレクトリを作成します。

% cd ~/Products
% mkdir rails-on-docker
% cd rails-on-docker

設定ファイルの作成

Dockerfile

Dockerファイルを作成し、以下を記述します。

Dockerfile

FROM ruby:3.1.2
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

このファイルは、Ruby on Railsアプリケーションのための開発環境を構築しています。各行の意味は以下の通りです。

  • FROM ruby:3.1.2
    • Ruby 3.1.2がインストールされた公式のDockerイメージを使用
  • RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
    • Node.jsとPostgreSQLクライアントをインストール
    • Node.jsはRailsのアセットパイプラインに必要で、PostgreSQLクライアントはデータベース接続に使用
  • WORKDIR /myapp
    • コンテナ内の作業ディレクトリを /myapp に設定
  • COPY Gemfile /myapp/Gemfile
  • COPY Gemfile.lock /myapp/Gemfile.lock
    • ホストマシンからGemfileとGemfile.lockをコンテナにコピー
  • RUN bundle install
    • Gemfileに記載された依存関係をインストール
  • COPY entrypoint.sh /usr/bin/
  • RUN chmod +x /usr/bin/entrypoint.sh
    • エントリーポイントスクリプトをコンテナにコピーし、実行可能にする
  • ENTRYPOINT ["entrypoint.sh"]
    • コンテナ起動時に実行されるコマンドを指定
  • EXPOSE 3000
    • コンテナがリッスンするポートを指定(Railsのデフォルトポート)
  • CMD ["rails", "server", "-b", "0.0.0.0"]
    • コンテナ起動時のデフォルトコマンドを指定
    • Railsサーバーを起動し、全てのインターフェースでリッスンするよう設定

Gemfile

Gemfileを作成し、以下を記述します。

Gemfile

source 'https://rubygems.org'
gem 'rails', '~>7'

Gemfile.lock

Gemfile.lockを作成します。中身は空で大丈夫です。

docker-compose.yml

docker-compose.ymlを作成し、以下を記述します。

docker-compose.yml

services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

このファイルは、Ruby on Railsアプリケーション(web)とそのデータベース(PostgreSQL)(db)の開発環境を定義しています。

このファイルを使用すると、docker-compose upコマンドで簡単に開発環境を起動できます。PostgreSQLデータベースとRailsアプリケーションが連携して動作し、コードの変更がすぐに反映される開発に適した環境が構築されます。

  • dbサービス
    • image: postgres
      • 公式のPostgreSQLイメージを使用します。
    • volumes
      • ホストマシンの./tmp/dbディレクトリをコンテナの/var/lib/postgresql/dataにマウント
      • これにより、データベースのデータが永続化される
    • environment
      • データベースのrootパスワードを 'password' に設定します。
  • webサービス
    • build
      • カレントディレクトリにあるDockerfileを使用してイメージをビルド
    • command
      • コンテナ起動時に実行されるコマンドを指定
      • rm -f tmp/pids/server.pid
        • 古いサーバーPIDファイルを削除(クリーンな起動のため)
      • bundle exec rails s -p 3000 -b '0.0.0.0'
        • Railsサーバーを起動
    • volumes
      • カレントディレクトリ(.)をコンテナの /myapp にマウント
      • これにより、ホストマシンでのコード変更がコンテナにすぐに反映される
    • ports
      • ホストの3000ポートをコンテナの3000ポートにマッピング
    • depends_on
      • このサービスがdbサービスに依存していることを指定(dbサービスが先に起動される)

entrypoint.sh

entrypoint.shを作成し、以下を記述します。

entrypoint.sh

#!/bin/bash
set -e
rm -f /myapp/tmp/pids/server.pid
exec "$@"

このスクリプトは、Dockerコンテナが起動する際に実行される重要なスクリプトです。

  1. 古いサーバープロセスIDファイルを確実に削除し、クリーンな状態でRailsサーバーを起動できるようにする
  2. Dockerfileで指定されたメインプロセス(Railsサーバー)を適切に起動する

これにより、コンテナの再起動時や開発中の繰り返しの起動時に、クリーンで一貫した環境でアプリケーションを実行できます。

  • #!/bin/bash
    • このスクリプトがbashシェルで実行されることを指定
  • set -e
    • エラーが発生した場合にスクリプトの実行を即座に停止するよう設定
    • これにより、エラーの早期検出と対応が可能になる
  • rm -f /myapp/tmp/pids/server.pid
    • Railsアプリケーションの一時ファイル(server.pid)を強制的に削除
    • このファイルは前回の実行時に残っている可能性があり、新しいサーバープロセスの起動を妨げる可能性がある
    • -fオプションは、ファイルが存在しない場合でもエラーを発生させずに続行することを意味する
  • exec "$@"
    • Dockerfileで指定されたCMDコマンド(rails server -b 0.0.0.0)を実行
    • $@は、このスクリプトに渡されたすべての引数を表す
    • execコマンドは、現在のプロセスを指定されたコマンドで置き換える
    • これにより、Railsサーバーがコンテナのメインプロセス(PID 1)として実行される

Dockerコンテナー起動

以下のコマンドを実行して、Docker Composeを使用して新しいRuby on Railsプロジェクトを作成します。

% docker compose run --no-deps web rails new . --force --database=postgresql
  • docker compose run
    • Docker Composeで定義されたサービスを一時的に実行
  • --no-deps
    • 依存サービス(dbサービス)を起動せずに実行
  • web
    • docker-compose.ymlで定義されたwebサービスを使用
  • rails new .
    • 現在のディレクトリ(.)に新しいRailsプロジェクトを作成
  • --force
    • 既存のファイルがある場合、それらを上書きする
  • --database=postgresql
    • デフォルトのデータベースとしてPostgreSQLを指定

Dockerコンテナーを再度ビルドします。

% docker compose build

Railsはデフォルトでlocalhost上でデータベースが動作していることを想定しているので、代わりにdbコンテナを指定する必要があります。そのため、代わりにdbコンテナのデータベースを使用するよう変更します。

また、データベースとユーザ名を、postgresイメージで設定されているデフォルトに合わせて変更します。

config/database.ymlを以下のように修正します。

config/database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test

以下のコマンドを実行して、Dockerコンテナーを起動します。

% docker compose up

Dockerコンテナーをバックグラウンドで起動したい場合、-dオプションをつけます。

% docker compose up -d

バックグラウンドで起動したDockerコンテナーを停止するには以下のコマンドを実行します。

% docker compose down

最後に、以下のコマンドを実行してデータベースを作成します(別のターミナルで実行)。

% docker compose run web rake db:create

Docker環境のデバッグ方法

Dockerで構築したRailsアプリケーションをpryを使ってデバッグする方法について説明します。

Gemfileの設定

Gemfileに以下を追記します。

Gemfile

group :development, :test do
  gem 'pry-rails'
  gem 'pry-byebug'
end

次に、以下のコマンドを実行します。

% docker-compose run web bundle install

Dockerfileの設定

Dockerfileに以下の行を追加して、pryが正しく動作するように設定します。

Dockerfile

ENV TERM xterm-256color

docker-compose.ymlの設定

docker-compose.ymlファイルのwebサービスに以下の設定を追加します。

docker-compose.yml

web:
  tty: true
  stdin_open: true

コードにブレークポイントを設定

デバッグしたい箇所にbinding.pryを追加します。

アプリケーションの起動

以下のコマンドでアプリケーションを起動します。

% docker-compose up

デバッグセッションの開始

以下のコマンドを実行してコンテナー名を確認します。

% docker ps
# => 右端の NAMES を確認

続いてコンテナーにアタッチします。

% docker attach CONTAINER-NAME

するとデバッグセッションが始まるので、変数の確認やコード実行してデバッグを行います。

デバッグの終了

デバッグセッションを終了するには、pryプロンプトで [Ctrl+P, Ctrl+Q] を入力します。[Ctrl+C] を入力するとコンテナーが停止してしまうので注意してください。

まとめ

Dockerを使用してRuby on Railsの開発環境を構築する方法を解説しました。Dockerを使うことで以下のような利点を得られます。

  1. 環境の一貫性:チーム全員が同じ環境で開発できる
  2. 簡単なセットアップ:新しいメンバーも簡単に環境を構築できる
  3. 移植性:異なるマシンや環境でも同じ設定で動作する
  4. 分離:他のプロジェクトや、システムの他の部分に影響を与えない

Dockerを使った開発環境の構築は、最初は少し手間がかかるかもしれません。しかし、一度セットアップすれば、その後の開発プロセスがスムーズになり、チームの生産性が向上します。

本記事を参考にして、Dockerを使用してRuby on Railsの開発環境を構築していただければと思います。

関連記事

【Rails】RSpecを使った自動テスト《システムスペック編》
# はじめに Railsでアプリケーションを開発する際、品質を担保するためにテストは欠かせません。その中でも、RSpecは多くの開発者に愛用されているテストフレームワークです。 今回は、RSpecを使ったRailsアプリケーションのテスト方 [...]
2024年7月11日 17:07
【Rails】RSpecを使った自動テスト《リクエストスペック編》
# はじめに Railsでアプリケーションを開発する際、品質を担保するためにテストは欠かせません。その中でも、RSpecは多くの開発者に愛用されているテストフレームワークです。 今回は、RSpecを使ったRailsアプリケーションのテスト方 [...]
2024年7月11日 16:06
【Rails】RSpecを使った自動テスト《コントローラースペック編》
# はじめに Railsでアプリケーションを開発する際、品質を担保するためにテストは欠かせません。その中でも、RSpecは多くの開発者に愛用されているテストフレームワークです。 今回は、RSpecを使ったRailsアプリケーションのテスト方 [...]
2024年7月11日 15:39
【Rails】RSpecを使った自動テスト《モデルスペック編》
# はじめに Railsでアプリケーションを開発する際、品質を担保するためにテストは欠かせません。その中でも、RSpecは多くの開発者に愛用されているテストフレームワークです。 今回は、RSpecを使ったRailsアプリケーションのテスト方 [...]
2024年7月11日 11:50
【Rails】RSpecを使った自動テスト《基本編》
# はじめに Railsでアプリケーションを開発する際、品質を担保するためにテストは欠かせません。その中でも、RSpecは多くの開発者に愛用されているテストフレームワークです。 今回は、RSpecを使ったRailsアプリケーションのテスト方 [...]
2024年7月10日 17:49
【Rails】デザインパターン「Concern」の基本情報と実装方法
# はじめに Ruby on RailsなどのMVCフレームワークで構築したWebシステムにはアンチパターンというものが存在します。システム開発におけるアンチパターンとは、避けるべき悪い設計や実装方法のことを指します。 MVCフレームワーク [...]
2024年7月10日 13:32
【Rails】デザインパターン「Form Object」の基本情報と実装方法
# はじめに Ruby on RailsなどのMVCフレームワークで構築したWebシステムにはアンチパターンというものが存在します。システム開発におけるアンチパターンとは、避けるべき悪い設計や実装方法のことを指します。 MVCフレームワーク [...]
2024年7月6日 22:50
【Rails】デザインパターン「Service Object」の基本情報と実装方法
# はじめに Ruby on RailsなどのMVCフレームワークで構築したWebシステムにはアンチパターンというものが存在します。システム開発におけるアンチパターンとは、避けるべき悪い設計や実装方法のことを指します。 MVCフレームワーク [...]
2024年7月6日 19:59