Docker Compose で Rails 7/ruby 3.1.2 + PostgreSQL環境を作る
はじめに
個人で開発しているアプリのサーバーサイドアプリケーション(Rails)のローカル開発環境をdocker-composeで作るにあたり、一度Docker公式サイトのクィックスタート: Compose と Railsで練習しておこうと思ってやってみたら、そのままやっても動かなかったしruby 2.3 / rails5系 だったので、zennに書いてみようと思いました。
ローカル開発環境をdocker-composeにしたくなった理由としては、PCをintel mac から m1macへ変えてから、bundle install
したところ、全然通らなくて通る様にするために色々インストールするのが怠いためです。
このレポジトリのコミットとdockerのクイックスタートをベースに環境構築の手順を書いていこうと思います。
わたしは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'
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
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:
docker-composeのwebサービス内でrails newする
上記の後(docker-compose.ymlまで作った後)、下記を実行する。
$docker-compose run web rails new . --force --database=postgresql
これで、下記のコミットみたいに色々ファイルが作られると思います。
わたしはこのタイミング(上記のrails new)でbundle install
しろというエラーが出たので、下記でwebサービス内にbashで入ってbundle install
したら、成功しました。
$docker-compose run web bash
$root@xxxxxxx:/myapp# bundle install
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"] %>
rails sever を起動してみる
ここまできたら、rails s
できるのでやってみます。docker-compose up
するとrails s
されます。
$ docker-compose up
これで、localhost:3000
にブラウザでアクセスしてみます。
そうすると、こんな感じのDBが無いというエラーが出ると思います。
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