【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】Paranoiaを使用した論理削除(ソフトデリート)
# はじめに Paranoiaは、Railsアプリケーションで論理削除(ソフトデリート)を実現するためのGemです。 論理削除は、データベースのレコードを物理的に削除するのではなく、削除フラグを設定することで「削除済み」とみなす方法です。こ [...]
2024年7月20日 21:33
【Rails】activerecord-multi-tenantを使用したマルチテナントアプリケーションの作成
# はじめに マルチテナントアプリケーションでは、複数の顧客(テナント)が同じアプリケーションを利用するため、データの分離が必要です。 activerecord-multi-tenantは、このようなマルチテナント環境をサポートするための便 [...]
2024年7月18日 16:50
【Rails】RubyとRailsにおけるattr_reader, attr_writer, attr_accessorの概念と使用方法
# はじめに RubyとRailsの開発において、`attr_reader`,`attr_writer`,`attr_accessor`は非常に便利なメソッドです。これらは、クラス内でインスタンス変数に対するゲッターおよびセッターメソッドを簡単に [...]
2024年7月17日 18:11
【Rails】RubyとRailsにおけるyieldの概念と使用方法
# はじめに RubyとRailsにおける`yield`は、メソッドやテンプレートの中で動的にコードブロックを実行する能力を提供し、これによってコードの再利用性と拡張性が大幅に向上します。本記事では、RubyとRailsにおける`yield`の概 [...]
2024年7月17日 13:15
【Rails】AASMを使用してオブジェクトの状態遷移を効率的に管理
# はじめに Railsアプリケーションにおいて、オブジェクトの状態管理は重要な課題の一つです。AASM (Acts As State Machine) gemは、複雑な状態遷移を効率的に管理します。本記事では、AASMの基本的な使い方を解説して [...]
2024年7月16日 18:00
【Rails】RSpec + Swagger + rswagでアプリケーションのAPIをテストおよびドキュメント化する方法
# はじめに Railsアプリケーションの開発において、APIのテストとドキュメント化は重要な要素です。 RSpecはテストフレームワークとして広く利用されており、SwaggerはAPIの設計とドキュメント化を支援します。これらを統合するr [...]
2024年7月16日 14:27
【Rails】mailcatcherを使用して開発環境でメール送信をテストする方法
# はじめに mailcatcherは、開発環境でのメール送信をキャプチャするためのツールです。ローカルで送信されたメールをブラウザ上で簡単に確認できるようにします。mailcatcherをRailsアプリケーションで使用する方法について説明しま [...]
2024年7月15日 16:37
【Rails】impressionistを使用してページビューやクリック数を追跡する方法
# はじめに impressionist Gemを使用してRailsアプリケーションでページビューやクリック数を追跡する方法について説明します。 # 実装方法 ## impressionist Gemのインストール まず、impre [...]
2024年7月15日 14:18