BETA

Docker で作った PostgreSQL を Rails の開発用の DB として使う方法

投稿日:2019-09-25
最終更新:2019-09-25

Rails での開発環境の DB について

Rails の開発環境をデフォルトの状態で作ると、DB には SQLite が使われますが、本番環境でそのまま SQLite を使うわけにはいきません。
当然、MySQL や PostgreSQL を使う事が一般的だと思います。
開発時に SQLite を使って、本番環境で別の DB を使うと、本番用の設定が必要だったり、本番環境固有の障害に悩まされることがあります。

そこで、Docker、Docker-Compose を使って DB だけでも本番と同様の DB を使用して、開発できたほうが良さそうです。
今回の構成を作るために、色々ググってみたのですが、Docker で Rails の環境と PostgreSQL を構築する方法などが大半で、テスト用と開発用の DB だけを Docker で用意して、Rails の実行環境はローカルで、という構成を解説した記事を見つけられませんでした。(そもそもそんなニーズがない!?)

ということで、今回は Rails の開発で使う、テスト用と開発用の DB(PostgreSQL) を Docker で構築する手順を紹介したいと思います。

前提

Docker と Docker Compose を使用します。
予め Docker for Mac などでインストールされた状態を想定しています。
また、コンテナの簡単な操作方法は把握していることを前提としているので、コンテナの起動方法、停止方法については解説しません。

今回の環境のバージョンは次のとおりです。

$ rbenv -v  
rbenv 1.1.2  

$ ruby -v  
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin18]  

$ docker -v  
Docker version 19.03.2, build 6a30dfc  

$ docker-compose -v  
docker-compose version 1.24.1, build 4667896b  

$ bundle exec rails -v  
Rails 5.2.3  

$ psql --version  
psql (PostgreSQL) 11.5 (Debian 11.5-1.pgdg90+1)  

rails new する

rails new コマンドでRails のプロジェクトを作成する際に、利用する DB として PostgreSQL を指定します。

bundle exec rails new sample_app -d postgresql  

database.yml の編集

database.yml を編集します。今回はこのような設定としました。

# config/database.yml  

default: &default  
  adapter: postgresql  
  host: 127.0.0.1  
  encoding: unicode  
  username: postgres  
  password: postgres  
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>  

development:  
  <<: *default  
  port: 5432  
  database: sample_app_development  

test:  
  <<: *default  
  port: 15432  
  database: sample_app_test  

docker-compose.yml の作成

続いて docker-compose.yml をプロジェクトルートに作成します。
今回はテスト用と開発用の2つのコンテナを作成します。
docker-compose.yml の内容は以下のとおりです。

version: '3'  
services:  
  postgres-development:  
    image: postgres:11.5  
    environment:  
      POSTGRES_USER: postgres  
      POSTGRES_PASSWORD: postgres  
      POSTGRES_DB: sample_app_development  
    volumes:  
      - ./data/devel:/var/lib/postgresql/data/  
    ports:  
      - 5432:5432  
  postgres-test:  
    image: postgres:11.5  
    environment:  
      POSTGRES_USER: postgres  
      POSTGRES_PASSWORD: postgres  
      POSTGRES_DB: sample_app_test  
    volumes:  
      - ./data/test:/var/lib/postgresql/data/  
    ports:  
      - 15432:5432  
    depends_on:  
      - postgres-development  

PostgreSQLのバージョンは 2019/09/24 現在で最新の 11.5 にしています。
ここは適宜バージョンを指定してください。
ports:に先程編集した database.yml に記載したポート番号を指定します。
また、PostgreSQL の data ディレクトリをプロジェクトルートの ./data ディレクトリにマウントしています。ここは Git で管理する必要がないので、後ほど .gitignore に追記します。

ここまで編集したら、docker-compose up -d でコンテナを立ち上げましょう。
テスト用のコンテナは開発用コンテナの実行後に起動するようにしています。

$ docker ps  
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES  
7fbf62ddc255        postgres:11.5       "docker-entrypoint.s…"   16 minutes ago      Up 2 seconds        0.0.0.0:15432->5432/tcp   sample_app_postgres-test_1  
54601c63e6d9        postgres:11.5       "docker-entrypoint.s…"   16 minutes ago      Up 2 seconds        0.0.0.0:5432->5432/tcp    sample_app_postgres-development_1  

localhost:3000 にアクセスしてみる

コンテナが2つ起動したら、bundle exec rails s を実行して、いつものように http://localhost:3000 にアクセスします。
いつもの Yay! が表示されると思います。

scaffold と minitest を試してみる

せっかくなので、適当に scaffold して minitest までしてみたいと思います。

bundle exec rails g scaffold User name:string email:string is_active:boolean  

migrateも問題なくできました。
開発用DB だけでなく、テスト用DB でも問題なくmigrateできました。

$ bundle exec rails db:migrate  
== 20190924153649 CreateUsers: migrating ======================================  
-- create_table(:users)  
   -> 0.0318s  
== 20190924153649 CreateUsers: migrated (0.0319s) =============================  

$ bundle exec rails db:migrate RAILS_ENV=test  
== 20190924153649 CreateUsers: migrating ======================================  
-- create_table(:users)  
   -> 0.0321s  
== 20190924153649 CreateUsers: migrated (0.0321s) =============================  

自動的に生成された fixture を使って簡単なテストを書きます。

# test/models/user_test.rb  
require 'test_helper'  

class UserTest < ActiveSupport::TestCase  
  def setup  
    @user = users(:one)  
  end  

  test 'should be valid' do  
    assert @user.valid?  
  end  
end  

モデルのテストを実行すると、正常に完了します。

$ bundle exec rails test test/models/user_test  
Running via Spring preloader in process 22590  
Run options: --seed 58136  

# Running:  

.  

Finished in 0.080793s, 12.3773 runs/s, 12.3773 assertions/s.  
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips  

.gitignore への追記

最後に PostgreSQL の data ディレクトリがマウントされている、プロジェクトルートの data ディレクトリを .gitignore に追記して Git の管理から除外します。
.gitignore の末尾にdataと追記します。

まとめ

本番環境とそっくりそのまま同じ環境を Docker で作ったほうがトラブルが少ない。というのは当然ですが、Web も AP も DB もなにもかも本番と同じ環境を作るのはちょっと手間かなあと思いました。
自主的に開発していて、せめて DB だけでも本番と同じように作れれば、と思って記事を書いてみました。
なにかの役に立てば幸いです。

今回テストで作成したサンプルはこちらのリポジトリです。

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@toyocyの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!