DockerでRuby on Railsの環境構築【初心者向け】

公式ドキュメントのQuickstart: Compose and Railsが分かりやすかったので、初心者向けにそれぞれ何をやっているか詳しく説明しながらやっていこうと思います。Docker for MacかDocker for Windowsを入れている人が対象です。

前提条件として、Docker Composeをインストールしておく必要があるのですがDocker for Mac、Docker for Windowsはデフォルトでインストールされているので必要ありません。

また、初心者向けとは書きましたがRailsはある程度触っている方が望ましいです。

完成したものをGitHubに上げておきます。

最初にプロジェクトのディレクトリを作成しておきましょう

$ mkdir docker-rails
$ cd docker-rails

プロジェクトの作成準備

アプリケーションのビルドには4つのファイルが必要です。まずはDockerコンテナに必要な依存関係等の情報を定義するDockerfileを作成します。

FROM ruby:2.3.3
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

1行目でベースイメージはrubyの2.3.3と定義しています。

apt-getはLinuxのパッケージ管理・操作のコマンドで、update -qqでエラーのみ表示してパッケージリストを取得・更新、install -yで全ての問い合わせにyesでインストールします。

build-essentialは標準開発ツール一式のパッケージ、libpq-devはPostgreSQLの開発用パッケージ、nodejsはサーバーサイドのJavaScript環境です。

RUNのコマンドは、Dockerイメージの上に新しいレイヤーとして実行され、コミットされたイメージはDockerfileの次のステップから利用されます。

WORKDIRはコンテナでの作業ディレクトリを指定します。

COPYは第一引数にホスト側のファイル、第2引数にコピー先のコンテナ側のファイルを指定します。

そのあとはbundle installで必要なGemをインストールし、コンテナ内の/myappにコピーしています。

 

次にRailsをロードするためのGemfileを作成します。ただ、これはrails newした時に上書きされてしまいます。

source 'https://rubygems.org'
gem 'rails', '5.0.0.1'

 

また、Dockerfileのビルドに必要なため空のGemfile.lockも作成します。

$ touch Gemfile.lock

 

最後にdocker-compose.ymlを作成します。

このファイルでは、アプリケーションを構成するサービスを定義します。今回はdb(データベース)とweb(Webサーバー)を定義しています。

version: '2'
services:
  db:
    image: postgres
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

versionというのはDocker Composeのファイルバージョンです。

imageにはベースイメージの指定、webの方は先ほどのDockerfileにrubyを指定しました。

buildにはDockerfileの場所を書きます。

commandにあるコマンドは、docker-compose upした時に実行されます。docker runで特定のコマンドを実行したいときはDockerfileCMDで指定するといいです。

volumeでは、ホスト側のカレントディレクトリをコンテナ側の/myappにマウントしています。

portsでは、ホスト側とコンテナ側のポートをリダイレクトしています。左側がホストです。

depends_onではコンテナの依存関係を定義しており、今回はデータベースと接続しています。

 

プロジェクトのビルド

プロジェクトをビルドしていきます。まずはdocker-compsoe runで先ほどのサービスwebのイメージをビルドし、新しいコンテナ内でrails newします。--forceオプションでGemfileを上書きし、--database=postgresqlでデータベースをPostgreSQLに指定しています。

$ docker-compose run web rails new . --force --database=postgresql

これによってファイル構成は以下のようになります。

$ ls -l
total 64
-rw-r--r--   1 vmb  staff   222 Jun  7 12:05 Dockerfile
-rw-r--r--   1 vmb  staff  1738 Jun  7 12:09 Gemfile
-rw-r--r--   1 vmb  staff  4297 Jun  7 12:09 Gemfile.lock
-rw-r--r--   1 vmb  staff   374 Jun  7 12:09 README.md
-rw-r--r--   1 vmb  staff   227 Jun  7 12:09 Rakefile
drwxr-xr-x  10 vmb  staff   340 Jun  7 12:09 app
drwxr-xr-x   8 vmb  staff   272 Jun  7 12:09 bin
drwxr-xr-x  14 vmb  staff   476 Jun  7 12:09 config
-rw-r--r--   1 vmb  staff   130 Jun  7 12:09 config.ru
drwxr-xr-x   3 vmb  staff   102 Jun  7 12:09 db
-rw-r--r--   1 vmb  staff   211 Jun  7 12:06 docker-compose.yml
drwxr-xr-x   4 vmb  staff   136 Jun  7 12:09 lib
drwxr-xr-x   3 vmb  staff   102 Jun  7 12:09 log
drwxr-xr-x   9 vmb  staff   306 Jun  7 12:09 public
drwxr-xr-x   9 vmb  staff   306 Jun  7 12:09 test
drwxr-xr-x   4 vmb  staff   136 Jun  7 12:09 tmp
drwxr-xr-x   3 vmb  staff   102 Jun  7 12:09 vendor

上書きにより新しいGemfileができたため、もう一度イメージをビルドする必要があります。

$ docker-compose build

 

データベース接続

ここまででアプリケーションは実行可能になりましたが、今のままだとデータベースはlocalhostだと認識されてしまいます。そのためpostgresイメージにセットされたdatabaseとusernameを変更する必要があります。

config/database.ymlを開いて以下のように変更してください。

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

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test

これで実行可能な状態になったため、docker-compose upします。

$ docker-compose up

docker-compose updocker-compose.ymlで定義したサービスを開始・再起動するものです。バックグラウンドで動作させたい場合は-dオプションをつけます。

最後にデータベースを作成するため、別ターミナルを開き次のコマンドを実行します。

$ docker-compose run web rake db:create

これでアプリケーションはDockerデーモン上で動作します。

http://localhost:3000で動作確認してみましょう。

 

アプリケーションの停止と再起動

無事アプリケーションを起動できたところで、停止と再起動の方法を説明します。

停止には次のコマンドを使用します。

$ docker-compose down

これにより、Dockerはコンテナを停止しコンテナ、ネットワーク、ボリューム、そしてdocker-compose up
で生成されたイメージを削除します。

docker-compose upを行ったターミナルでCtrl-Cで停止したいかもしれませんが、これを行うとアプリケーションを再起動した時にエラーがでる恐れがあります。

そのときはtmp/pids/server.pidを削除し、再起動してください。

再起動はdocker-compose upで行えます。

 

今回は以上となります。さらに詳しくみたい方は公式ドキュメントを参照してください。