この記事では、Dockerを用いてRuby on Rails(以下、rails)の 5.x 系における開発環境を構築する方法を紹介します。
※Rails 6.x 系で Docker 環境を作りたい場合は こちら をご覧ください。
Docker で環境構築をするメリットとは?
通常、rails の初学者の方はマシンに直接インストールして開発環境を構築する人がほとんどだと思います。
しかし、環境の微妙な際(Rubyのバージョンや環境変数など)によってつまづいた場合、
そのトラブルシューティングには多くの時間を要してしまうかと思います。
そこで、Dockerで仮想環境上にrailsの環境を構築してあげることで
どのマシン上の開発環境でも等しい動作を行うことができるため、環境の差異によるエラーを避けることができます。
環境をいじりすぎた時には最悪一度リセットを出来るというのもメリットですね。
また、作成したアプリケーションを本番環境として外部へ公開しようとするときにも
開発環境と本番環境での違いを最小限に抑え、安定したアプリケーションとして稼働させることができます.
Dockerで仮想環境を作って公開するなんて難しそうと思うかもしれませんが、
最近ではAWSといったクラウドサービスでもDockerコンテナをそのまま実行できるECS等のサービスが整っているので
Dockerで作った環境を公開するのも楽になってきています。
前提条件
マシンに Docker がインストールされていること
Docker をインストールしていない人は、公式サイトから Docker のインストーラをダウンロードしてインストールしておきましょう。
→Docker公式
また、任意の作業フォルダを作成しておきます。
ここでは "rails-docker" というフォルダを作成し、その中で作業していくことにします。
$ mkdir rails-docker
$ cd rails-docker
Docker関連ファイルの準備
rails-docker 内に以下4つの空ファイルを準備しておきます。
VScode を利用しているなら新規ファイルの作成で作ったり、
Mac のターミナルから touch コマンドを使ってもよいです。
.
├── Dockerfile # 新規作成
├── Gemfile # 新規作成
├── Gemfile.lock # 新規作成
└── docker-compose.yml # 新規作成
Dockerファイルの解説
Dockerでは、Dockerfileというファイルに基づいてコンテナのビルドが行われ、
Docker Image(コンテナの雛形)が作成されることになります。
まず Dockerfile の全文を記載します。
使用する Ruby のバージョンは 2.7.0 としています。
FROM ruby:2.7.0
RUN apt-get update -qq && apt-get install -y build-essential nodejs
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app
箇条書きとはなりますが、それぞれの意味を解説します。
- FROM ruby:2.7.0
- 公開されている ruby インストール済みコンテナのうち、Rubyのバージョンが 2.7.0 であるものを引っ張ってきます。
- RUN apt-get update -qq && apt-get install -y build-essential nodejs
- Rails の実行に必要なパッケージをインストールしています
- RUN mkdir /app
- Rails のプロジェクトファイルを作成するアプリディレクトリを作成
- WORKDIR /app
- 作業用のディレクトリを指定
- COPY Gemfile /app/Gemfile
- 自分のマシン(PC)上にある Gemfile をコンテナの作業用ディレクトリに移動させ、コンテナから利用できるようにします
- Gemfile.lock も同様
- RUN bundle install
- Gemfileに記載されているgemを一括インストール
- COPY . /app
- Dockerファイルが置いてあるフォルダのファイルすべてをコンテナ内の app ディレクトリにコピー
- Rails の実行に必要なファイルをコンテナに含めるためにコピーしています
Gemfile の解説
Ruby では Gemfile というファイルで環境で使いたい gem を定義することができます。
gemとはRubyのライブラリのことをいいます。
gemはRubyGemsと呼ばれるRuby用のパッケージ管理システムで管理されており、RubyGemsが提供するgemコマンドを通じてインストール等ができます。
source 'https://rubygems.org'
gem 'rails', '5.2.1'
また少し解説します。
- source 'https://rubygems.org'
- gem のダウンロード元を指定
- gem 'rails', '5.2.1'
- インストールする gem である rails というパッケージ名と、バージョンを指定
- 今回は rails のバージョンは 5.2.1 を指定しています
- どのバージョンを指定してもよいのですが rails 6 以降は webpacker, yarn が必要になるので注意してください
- ここでは簡単に検証するため rails 5 系を使用
Gemfile があるディレクトリで "bundle install" コマンドを実行すると、
Gemfile の定義に従って、定義した gem をインストールすることができます。
先ほど解説した Docker ファイルでも、Gemfile をコンテナの作業用ディレクトリにコピーして
そのフォルダ内で bundle install を実行するように指定していましたね。
Gemfile.lock の解説
実は Gemfile.lock は最初の時点では何も書き込む必要がありません。
これは直接編集するようなファイルではなく、
Gemfile に基づいて bundle install を実行した後に
インストールされた gem が Gemfile.lock に一覧として記述されるようになります。
使い方としては、Gemfile.lock を参照すればインストールされている gem とバージョンが分かり、
Gemfile.lock から bundle install を実行することもできるので
完全に同じ環境をもう一度作りたいときや、多人数で開発をするときに Gemfile.lock が使われます。
Gemfile だけでも良いのでは?と思った鋭い方に補足しますと、Gemfile では実はこういう書き方もできることが理由の一つになっています。
gem 'rails', '~> 5.2.1'
この場合、bundle install でインストールされる rails のバージョンは 5.2.1 以上であるものの
実際にインストールできる(公開されている)バージョンはその時点によって変わってきます。
しかし Gemfile.lock では Gemfile に従ってインストールしようとした時に実際にインストールされた gem 本体と具体的なバージョン、
付随して必要となるためにインストールされたパッケージまで記録されます。
少し整理すると Gemfile は「アプリで必要な gem の一覧」であり、
一方の Gemfile.lock は「Gemfile に従った結果、実際にインストールした gem の情報」が記述されることになります。
docker-compose.yml の解説
この yml ファイルは Docker Compose で使用されます。
Docker Composeは、複数のコンテナで構成されるアプリケーションについて
Dockerイメージのビルドや各コンテナの起動・停止といった管理を行うためのツールです。
Docker Composeでは、Dockerビルドやコンテナ起動のオプションも含め、複数のコンテナのための定義を docker-compose.yml というファイルに記述し、
それを利用して Docker イメージのビルドやコンテナ起動をすることができます。
開発環境のように、Rails をそれ単体で動かすならば Dockerfile だけでもよいのですが
Rails を動かすためのアプリケーションサーバに加え、
実際に公開するときにはインターネットからのアクセスを受け付けるための Web サーバや、
またデータを保存・処理するためのデータベースサーバも用意することがあります。
version: '3'
services:
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/app
ports:
- 3000:3000
depends_on:
- db
tty: true
stdin_open: true
db:
image: mysql:5.7
volumes:
- db-volume:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
volumes:
db-volume:
rails ではデータベースも必要になるため、WebサーバだけではなくMySQLを用いたデータベースサーバのコンテナも構築します。
ここでは詳解しませんが、web という欄の中の「depends_on」で rails が連携するデータベースサーバ(コンテナ)を名前で指定しています。
rails の立ち上げ
rails プロジェクトの作成 (rails new)
docker-compose.yml が置いてあるフォルダ(rails-dockerフォルダ)で以下の docker-compose コマンドを実行します。
$ docker-compose run web rails new . --force --database=mysql
コマンドについて、オプション含め少し読み方を解説します↓
- docker-compose: docker-compose というツールをつかって
- run: 以下のコマンドを実行します
- web: web コンテナで
- rails new: rails で新しいプロジェクトを作成する
- . : 現在のディレクトリに対して
- --force: 既存の file (ここでは Gemfile, Gemfile.lock) は上書きする形で
- --database=mysql: ただし rails のデータベースには MySQL を使用します
という意味を持っているのです。
この一行のコマンドを実行すると数分単位で処理に時間がかかるので、チョコレートでも食べながら気長に待ちましょう。
build の実行
Gemfile に追記された gem のインストール、
および作成されたファイルをコンテナ内に取り込むため build を実行します。
$ docker-compose build
データベース設定ファイルの編集
build が完了したら、rails で使用するデータベースファイルの設定を編集します。
config ディレクトリ内の database.yml というファイルが対象です。
default: &default
adapter: mysql2
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: password # 追加
host: db # 変更
password は docker-compose.yml で指定したパスワードと合わせる必要があります。
...
environment:
MYSQL_ROOT_PASSWORD: password # ここと合わせる
...
また、host の欄は MySQL コンテナ名を設定しています。
コンテナの起動
コンテナを起動するため、次のコマンドを実行します。
$ docker-compose up -d
docker-compose up がコンテナをdocker-compose.yml に基づいて起動するコマンドであり、
オプションの「-d」によりバックグラウンドで起動させることができます。
データベースの作成
いまはまだコンテナが起動しただけであり、データベースは作成されていないので
次のコマンドを実行してデータベースを作成します。
$ docker-compose run web bundle exec rails db:create
rails を実行している web コンテナで、rails db:create (=データベースの新規作成)を実行する処理となっています。
rails 開発用サーバの起動確認
これで無事に rails の開発用サーバが起動したことになります。
ブラウザのアドレスバーに localhost:3000 と入力し、起動を確認してみましょう。
rails ではお馴染みの画面が表示されれば完了です。
コンテナの停止
開発用サーバを止めるため、コンテナを一括で停止するには以下のコマンドを実行します。
$ docker-compose down
また立ち上げたいときには docker-comopose up -d を実行しましょう。
最後に
これによって作られるファイルの一式は Github にあげています。
フォルダ構成が分からなくなったり、自分の環境でうまくいっているか比較して確かめたい方はご参照ください。