🐳

Docker Compose で Rails 7/ruby 3.1.2 + PostgreSQL環境を作る

2022/07/09に公開

はじめに

個人で開発しているアプリのサーバーサイドアプリケーション(Rails)のローカル開発環境をdocker-composeで作るにあたり、一度Docker公式サイトのクィックスタート: Compose と Railsで練習しておこうと思ってやってみたら、そのままやっても動かなかったしruby 2.3 / rails5系 だったので、zennに書いてみようと思いました。

ローカル開発環境をdocker-composeにしたくなった理由としては、PCをintel mac から m1macへ変えてから、bundle installしたところ、全然通らなくて通る様にするために色々インストールするのが怠いためです。

このレポジトリのコミットとdockerのクイックスタートをベースに環境構築の手順を書いていこうと思います。
https://github.com/HikaruSato/rails7_app
https://docs.docker.jp/compose/rails.html

わたしはdockerに詳しくないので適当なことを書いてるかもしれないのでそういうところがあったらご指摘ください🙏初心者向けな内容かもしれません。

準備

わたしの動作環境は下記です。M1 Macですが、多分intel Macでも同じ手順でできるんじゃないかと思います。

  • MacBook Pro (13-inch, M1, 2020
  • メモリ:16 GB

railsアプリ環境を作る用の適当なフォルダを作成し、そのフォルダに移動。
適当にフォルダ名はrails7_appとしてます。

$mkdir rails7_app
$cd rails7_app

add Gemfile, Gemfile.lock

GemfileとGemfile.lock(空ファイル)を追加する。Gemfileは後で rails new するため、railsだけいれる。

Gemfile

source 'https://rubygems.org'
gem 'rails', '~> 7.0.0'

https://github.com/HikaruSato/rails7_app/commit/8542dd17163049e80a7f945645278ef43a37143b

add Dockerfile

docker公式サイトと異なっているのは、 vim (コンテナにbashで入って編集するのに便利)もインストールしているところくらいです。

Dockerfile

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

https://github.com/HikaruSato/rails7_app/commit/3ff06f0b660c2810109d2da02eea52756529dac5

add docker-compose.yml

ここがちょっと公式と異なっています。docker-compose.yml内にコメントで説明を書いて見ます。

docker-compose.yml

version: '3'
services:
  db:
    image: postgres
    # dbのユーザー名とパスワードでこれが無いとdbが起動できなかった
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    # 無くても動くけど指定しておくとdocker-composeを停止してもdbの内容が永続化されるため、指定することが多いと思われる
    # https://matsuand.github.io/docs.docker.jp.onthefly/storage/volumes/
    volumes:
      - postgres_volume:/var/lib/postgresql/data
    # 無くても動くが指定しておくとコンテナ停止時にサービスが再起動してくれる
    # https://docs.docker.jp/v19.03/config/container/start-containers-automatically.html
    restart: always
  web:
    build: .
    # tmp/pids/server.pidが残ってたら `A server is already running. ~~` のエラーでrailsを起動できないので事前に消してから、`rails sever` する
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    # 上記のdbイメージで指定したユーザー名とパスワードをrails側でも指定するため環境変数に設定。
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    # ホストのカレントディレクトリ(.)とイメージ内の/myappディレクトリを同期させている
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    restart: always # コンテナが停止すると常に再起動
    tty: true # 疑似ターミナル (pseudo-TTY) を割り当て。https://docs.docker.jp/compose/compose-file/index.html#tty
    stdin_open: true # サービス コンテナに標準入力を割り当てて実行するよう設定(https://docs.docker.jp/compose/compose-file/index.html#stdin-open)。
    depends_on:
      - db
volumes:
  postgres_volume:

https://github.com/HikaruSato/rails7_app/commit/a6164b5c841fd59c40cc5acd05d4adfeea14fba9

docker-composeのwebサービス内でrails newする

上記の後(docker-compose.ymlまで作った後)、下記を実行する。

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

これで、下記のコミットみたいに色々ファイルが作られると思います。
https://github.com/HikaruSato/rails7_app/commit/f0b974d1d44490394161bb470c362a9f36afc293

わたしはこのタイミング(上記のrails new)でbundle installしろというエラーが出たので、下記でwebサービス内にbashで入ってbundle installしたら、成功しました。

$docker-compose run web bash
$root@xxxxxxx:/myapp# bundle install

https://github.com/HikaruSato/rails7_app/commit/8a4578bbeaced35e92bd2edd19b0ae0765488be9

dbのユーザー名とパスワードを指定

docker-compose.ymlで指定したdbのユーザー名とパスワードを config/database.ymlに指定します。production:のusername/password方はこの構築手順的にはどっちでもいいのですが、一旦消しておきます。

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
+  username: <%= ENV["POSTGRES_USER"] %>
+  password: <%= ENV["POSTGRES_PASSWORD"] %>
...
production:
  <<: *default
  database: myapp_production
-  username: myapp
-  password: <%= ENV["MYAPP_DATABASE_PASSWORD"] %>

https://github.com/HikaruSato/rails7_app/commit/f62c35638f9890280921c328087765b7dd44833d

rails sever を起動してみる

ここまできたら、rails sできるのでやってみます。docker-compose upするとrails sされます。

$ docker-compose up

これで、localhost:3000にブラウザでアクセスしてみます。
そうすると、こんな感じのDBが無いというエラーが出ると思います。

NoDatabaseError

rails sを止めるにはCtrl+Cで止めれます。

DB作成

上記でDBが無いということのなので、DB作成します。

$ dc exec web bash
$root@xxxxxxx:/myapp# rails db:create

# webイメージのbashを抜ける
$root@xxxxxxx:/myapp# exit

もう一回rails s

rails sやってみます。docker-compose upするとrails sされます。

$ docker-compose up

これで、localhost:3000にブラウザでアクセスしてみます。
railsのマークが表示されたら完成です。

コンテナ内のrails アプリを debug

docker-compose up後、dockerのコンテナにアタッチ。

# `docker ps` で対象コンテナ名を確認して、コンテナにアタッチ
# 抜ける時は control + p + q で抜ける
$ docker attach ${コンテナ名}

ブレークポイントを設定したいrubyのコードに debuggerを入力。

それが実行されるページやAPIを実行すると、debuggerのところで止まって、デバッグできる(デバッグ方法はdebug gem参照 https://github.com/ruby/debug)。変数とかを入力すると変数の値が見れたりする。

Discussion