dockerでRailsの開発環境を手軽に準備

Ruby on Railsの開発環境は、新しいバージョンのruby環境とbundlerがあれば比較的簡単に整備できます。

dockerhubの Ruby公式イメージはbundlerまでセットアップ済みのため、Rails環境を手軽に入手するのに役立ちます。

Ruby on Railsで新たにアプリケーションを開発する際、(1)DBMSやAPサーバなどの稼働環境を構築する、(2)rails newしてコードを書いていく、という2系統のタスクがあります。

後述のとおり、(1)については Rails実行環境の構築で解説しています。既存のRuby on Railsプロジェクトがある場合などは、ここからスタートしたいケースが多いと思います。

また、(2)はとにかく新規プロジェクトのコードを書き始めたいケースです。記事後半の dockerでいきなりrails newで解説しました。rbenvなどと格闘することなく、プロジェクトのスケルトンを生成できます。

dockerを利用するメリットについては、「 Web開発環境をdockerで構築するメリット」で解説しています。

Rails実行環境の構築

前提

  • dockerセットアップは終わっている
  • RailsプロジェクトのトップディレクトリにGemfileを置いてbundle installするスタイル
  • ホストOSのあるディレクトリにRailsプロジェクトのファイル一式を置く
    • 開発中のプロジェクトディレクトリをgit cloneしてホストOSに置いておくこともできる
    • OSXのDocker Toolboxの場合は、OSXのディレクトリにRailsプロジェクトを置く
  • PostgreSQLやMySQLを利用したい場合は別途接続設定が必要

手順

  1. Railsプロジェクトをボリュームマウントして、ruby:latestを起動
    • $ docker run -it -p 3000:3000 -v /path/to/rails-project:/opt --name railsdev ruby:latest /bin/bash
    • この例では、dockerの/optにRailsプロジェクトがmountされる。また、コンテナ名はrailsdev
  2. Rails関係のgemを一式インストール
    • # cd /opt
    • # bundle install
  3. Railsが使える状態になっているので、rails newしたり、データベースにデータ投入したりする(一般的なRailsの開発手順)
  4. Rails Serverを起動
    • # rails s -b 0.0.0.0
  5. ブラウザから、dockerの3000番ポートにアクセスする

使い方

rubyコンテナにはviなどは入っていないので、ホストOS側でソース編集する方が使いやすいでしょう。ボリュームとしてdockerコンテナからも見えているので、編集後にdockerを再起動する必要はありません。

githubなどもホストOS側のクライアントを利用すれば、環境別にgitクライアントをセットアップする必要がありません。

一度作ってしまえば、dockerインスタンスの操作はdocker start railsdevなど一般的なdockerコマンドが使えます。

データベースは別途マイグレーション実行や、バックアップからデータリストアなどが必要になりますが、これは一般的なRails開発手順の範疇です。

SQLiteであればrubyコンテナにgemをインストールするだけで必要なものはそろいます。mysql2アダプタをインストールして既存のDBの接続設定を書けばMySQLも使えることを確認済みです。

bundlerがシステムグローバルにインストールされるため、railsコマンドをbundle exec railsのようにプレフィクスをつけることなく利用できるのはシンプルで便利です。

複数のRailsプロジェクトを準備しなくてはならないケースでもdockerコンテナの環境はそれぞれ独立しているため、プロジェクト間のgem混在などに悩まされることなくポータブルな環境を準備できます。

dockerでいきなりrails new

とりいそぎ、開発作業に着手していけば、同じコードベースである程度汎用の環境で動作するため、実行環境の構築はテスト段階まで先送りすることも可能です。

そこで、手軽にrails newできる環境があると助かります。

RubyとRailsはPHPなどと比べてバージョンアップが頻繁に起こるため、ローカルのPCにそのままインストールすると一度入れた環境がレガシー化したり、rbenvやbundlerのインストールに手間どったりするケースに遭遇したりします。

dockerを活用することで、RubyとRailsのインストールをすることなく、いきなりrails newできます。

rails new の手順

手順は、 docker hubのRails公式イメージの”Bootstrap a new Rails application”項の解説のとおりです。

$ docker run -it --rm -v `pwd`:/usr/src/app -w /usr/src/app rails rails new webapp

を実行すると、カレントディレクトリにwebappというRaisアプリのプロジェクトが生成されます。(DB指定やbundlerをスキップする-d postgresql --skip-bundleも必要に応じて付けられます)

単なるdockerの説明になってしまいますが、このコマンドの実行内容を補足すると以下のように動作しています。

  1. “rails”という名前の公式イメージをdocker hubからダウンロード
  2. 使い捨てのdockerインスタンスを起動(–rmオプション)、ローカルホストのカレントディレクトリをコンテナの/usr/src/appにマウント
  3. /usr/src/appでrails new webappを実行
  4. dockerコンテナを停止、カレントディレクトリにwebappプロジェクトが残る

途中でイメージのダウンロードやbundle installを自動実行するため相応の待ちがありますが、基本的にはトラブルフリーで進みます。

なお、上のコマンドラインはリンク先の公式サイトと一部異なります。

これはOSXのboot2dockerで実行しているため、Linuxホストで直接実行した場合と環境が異なるためです。

ただしdockerの操作に慣れることは必要

ひとまず、ワンライナーでrails newを実行できました。実際にrbenvなどで苦戦してくると、何も準備しなくて良いことを新鮮に感じます。

ただ、前提としてdockerは必要です。

今回実行したdockerインスタンスは使い捨てのため、生成されたRailsアプリを実行するにも新たにdockerインスタンスを立ち上げる必要があります。

Rails公式イメージのページの冒頭で解説されている、rails:onbuildのイメージ手順が使えます)

けっきょく、rubyの環境構築を頑張るか、dockerを頑張って覚えるか、という選択になります。

dockerは、最近のディストリビューションであれば標準のパッケージマネージャでインストールできますし、OSXでも Docker Toolboxが整備されています。

長いコマンドラインオプションを覚えることがハードルと言えますが、前提ライブラリを1つひとつ手でインストールするよりは生産的なように思います。

Railsが起動しない場合のデバッグ手順

dockerで起動を自動化すると、Railsが起動しない事象に遭遇したときのデバッグが分かりづらくなる場合があります。

典型的な挙動としては、rubyのアプリ・サーバーがうまく起動できずコンテナが再起動を繰り返すケースです。

この場合の対処法の基本方針としては、Railsサーバーを起動しない設定でdocker runしてrailsを手動起動が手っとり早いと思います。

多くの構成では、docker起動オプションのENTRYPOINTに、bundle exec rails sunicorn_railsなどを指定していると思います。

ENTRYPOINTやCMDのプロセスが異常終了するとコンテナごと終了してしまうので、デバッグ時には一時的に別のコマンドラインを指定して異常終了しないよう設定します。

(なお、起動中のコンテナのENTRYPOINTに何がセットされているかを確認するには、docker inspectを使えます)

具体的には、tail -f /dev/nullなどの何も機能せず動作し続けるコマンドが適しています。

このようなデバッグ用のDockerfileで一時的なコンテナイメージを作り、docker run -it --rm this_temporary_debug_image bashなどでコンテナのシェル環境に入ります。

この環境でrails sunicorn_railsを起動することで、コンソール上で直接エラーを観察できます。

中馬崇尋
Chuma Takahiro