はじめに
本記事は、Dockerを利用してRails 7とMySQLの開発環境を構築するための詳細なチュートリアルを提供します。
具体的には、以下のような内容を説明します。
- Dockerのインストール
- コンテナイメージのビルド
- Railsプロジェクトの作成
- データベースの準備
- コンテナの起動と削除
- 簡単な CRUD アプリケーションの作成
前提条件の確認
今回のチュートリアルを実施していくにあたり、 開発に使用する PC に Docker をインストールしておきます。
Docker をインストールしていない人は、 公式サイトからインストーラをダウンロードしてインストールしておきましょう。
また、デスクトップなどに任意の作業フォルダを作成しておきます。
ここでは “rails-docker” というディレクトリを作成し、 その中で作業していくことにします。
mkdir rails-docker
cd rails-docker
Docker で Ruby on Rails を動かす準備
空ファイルの準備
まずは rails-docker ディレクトリローカルの中に 以下の 5 つの空ファイルを作成しましょう。
- Dockerfile
- docker-compose.yml
- Gemfile
- Gemfile.lock
- entrypoint.sh
一つひとつファイルの作るのが面倒であれば 以下のコマンドをターミナルで叩くと一発で作れます。
touch {Dockerfile, docker-compose.yml, Gemfile, Gemfile.lock, entrypoint.sh}
作成できたら、Gemfile.lock 以外の 4 ファイルを編集していきます。
RailsとMySQLの開発環境構築に必要なDockerfileの準備
Docker では、 Dockerfile という名前のファイルで定義した通りに コンテナイメージの作成が行われます。
そのため、Rails を動かすために必要なパッケージのインストール等は この Dockerfile の中で指定することになります。
また、Dockerfile 内でベースとなるコンテナイメージを指定することも可能です。
空の Linux から Ruby をインストールしていくのは大変なので、 通常は任意のバージョンの Ruby が最初からインストールされている Ruby 公式のイメージを使用するのがいいでしょう。
今回は、執筆時点で最新のイメージである Ruby 3.2.2 を指定してみましょう。
Dockefile を以下のように編集してください。
Dockerfile
FROM ruby:3.2.2
ARG RUBYGEMS_VERSION=3.3.20
# 作業ディレクトリを指定
WORKDIR /sample_rails
# ホストのGemfileをコンテナ内の作業ディレクトリにコピー
COPY Gemfile Gemfile.lock /sample_rails/
# bundle installを実行
RUN bundle install
# ホストのファイルをコンテナ内の作業ディレクトリにコピー
COPY . /sample_rails/
# entrypoint.shをコンテナ内の作業ディレクトリにコピー
COPY entrypoint.sh /usr/bin/
# entrypoint.shの実行権限を付与
RUN chmod +x /usr/bin/entrypoint.sh
# コンテナ起動時にentrypoint.shを実行するように設定
ENTRYPOINT ["entrypoint.sh"]
# コンテナ起動時に実行するコマンドを指定
CMD ["rails", "server", "-b", "0.0.0.0"]
なお、Rails 6 までは Webpacker を動かすために Node.js が必要でした。
しかし、Rails 7 では Webpacker がデフォルトでインストールされなくなるため、 Node.js は不要になります。
初期設定がシンプルになるのは嬉しいですね。
複数のDockerコンテナを動かす準備
今回のように Rails を動かすコンテナサービス以外にも MySQL (DB) を動かすコンテナサービスを起動し、サービス間での連携が必要な場合には Docker Compose というツールを利用します。
Docker Compose は、複数のコンテナで構成されるアプリケーションについて Docker イメージのビルドや、各コンテナの起動・停止といった管理を行うためのツールです。
Docker Compose では、Docker ビルドやコンテナ起動のオプションも含め 複数のコンテナのための定義を docker-compose.yml というファイルに記述することで、 Docker イメージのビルドやコンテナの起動を一括で行うことができるようになります
では、docker-compose.yml の中身を以下のように編集します。
docker-compose.yml
version: '3'
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: mydatabase
MYSQL_USER: user
MYSQL_PASSWORD: password
volumes:
- mysql_volume:/var/lib/mysql
ports:
- '3306:3306'
command: --default-authentication-plugin=mysql_native_password
web:
build:
context: .
dockerfile: Dockerfile
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails tailwindcss:build && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/sample_rails
ports:
- 3000:3000
stdin_open: true
tty: true
depends_on:
- db
volumes:
mysql_volume:
db
という欄で MySQL (DB) のコンテナサービス(以下、コンテナ)の起動に関する設定をし、 web
という欄で Rails (アプリ) サービス起動に関する設定をしています。
この db
という名前で、後ほど Rails から MySQL にアクセスするための設定をしていきます。
これまでは MySQL といえばバージョン 5.7 が人気でしたが、 2020 年 4 月にバージョン 8.0 がリリースされたことで、 5.7 から 8.0 への移行が進んでいます。
Qiita 等で Docker と Rails の情報を探すとまだまだ 5.7 を使っている記事が多いですが、今から始めるなら 8.0 に慣れておくことをおすすめします。
また、コマンドのうち以下の部分は Rails 7 からの新機能である Tailwind CSS を使うためのコマンドです。
command: (略) bundle exec rails tailwindcss:build && (略)
Tailwind CSS は、CSS を簡単に書けるようにするためのフレームワークであり、私は現場でもよく使っているので、今回も使えるようにしてあります。
もし Tailwind CSS を使わない場合は、この部分を削除しても OK です。
Gemfile の編集
Gemfile とは、Rails で使用する Gem を管理するためのファイルです。
今回はもちろん Rails 7 を使うので、Gemfile の中身を以下のように編集します。
Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 7.0'
これで Rails のバージョンのうち、メジャーバージョンが 7 であることを指定できました。
entrypoint.sh の編集
続いで、entrypoint.sh を編集します。
entrypoint.sh は、コンテナ起動時に実行するスクリプトを記述するためのファイルです。
entrypoint.sh
#!/bin/bash
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f /sample_rails/tmp/pids/server.pid
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
ここでは、Rails でよくある server.pid
のエラーを回避するために、 一度 server.pid
を削除しています。
また、最後の exec "$@"
は、コンテナ起動時に実行するコマンドを指定するためのものです。
これにより、Dockefile で指定した CMD ["rails", "server", "-b", "0.0.0.0"]
が実行されます。
これでスタート時点で必要なファイルは準備できました!
Ruby on Rails プロジェクトの準備
Rails プロジェクトの作成
まず docker-compose コマンドを使って rails new
を実行し、 Rails プロジェクトを作成しましょう。
以下のコマンドを実行してください。
docker-compose run web rails new . --force --no-deps --database=mysql --css=tailwind --skip-jbuilder --skip-action-mailbox --skip-action-mailer --skip-test
docker-compose run
に続けてサービス名を指定し、 さらにコンテナ内で実行したいコマンド(=rails コマンド) を続けています。また、今回は MySQL を使用するため、 --database=mysql
を指定しています。
他には、--css=tailwind
というオプションを指定しており、これにより Tailwind CSS を使うための設定が自動で行われます。
--skip-jbuilder
や --skip-action-mailbox
などは、今回は必要がない機能をスキップするためのオプションです。
コマンド実行後、rails new
した時と同じように、ディレクトリ内に app
や config
などのフォルダが作成されていることが確認できると思います。
Dockerコンテナイメージの作成
次は、前項で作成した Docker 関連ファイルを使って 早速コンテナイメージをビルドします。
docker-compose build
ここで数分かかることがあるので、気長に待ちましょう。
MySQL データベースの準備
では次に、データベースの準備をしていきましょう。
まずは Rails で使用しているデータベースファイルの設定を編集します。
config ディレクトリ内の database.yml というファイルが対象です。
下記のように、まるっと書き換えてください。
config/database.yml
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: user
password: password
host: db
development:
<<: *default
database: sample_rails_development
test:
<<: *default
database: sample_rails_test
ポイントは、host
の欄が db
であることです。
db
は docker-compose.yml で指定した MySQL のコンテナ名ですね。
同じ docker-compose.yml で指定したコンテナ間であれば、 コンテナ名をホストとして名前解決してアクセスすることができます。
さて、これで Rails がデータベースと連携できるようになったので rails db:create
コマンドを docker-compose 経由で実行して データベースを作成しておきましょう。
docker-compose run web rails db:create
コマンド実行後、以下のように表示されれば OK です。
$ docker-compose run web rails db:create
[+] Running 1/0
⠿ Container rails-docker-db-1 Running 0.0s
Created database 'sample_rails_development'
Created database 'sample_rails_test'
次はいよいよ、docker-compose で Rails サーバを起動させましょう。
動作確認
コンテナの起動
コンテナを起動するため、次のコマンドを実行します。
docker-compose up -d
docker-compose up
は、コンテナ docker-compose.yml に基づいて起動するコマンドです。
コンテナ起動時にコンテナ内で実行させたいコマンド (= rails s
) は Dockerfile で設定しているので、 コンテナを起動させると Rails サーバが立ち上がります。
また、オプションの -d
を付けるとバックグラウンドで起動させることができます。
以下のように表示されれば OK です。
$ docker-compose up -d
[+] Running 2/2
⠿ Container rails-docker-db-1 Running 0.0s
⠿ Container rails-docker-web-1 Started 0.5s
念のため、起動したコンテナを確認してみましょう。
以下のように、2つとも running
と表示されていれば OK です。
$ docker-compose ps
NAME COMMAND SERVICE STATUS PORTS
rails-docker-db-1 "docker-entrypoint.s…" db running 0.0.0.0:3306->3306/tcp, 33060/tcp
rails-docker-web-1 "entrypoint.sh bash …" web running 0.0.0.0:3000->3000/tcp
これで無事に Rails の開発用サーバが起動したことになります。
画面表示の確認
ブラウザのアドレスバーに http://localhost:3000/ と入力し、起動を確認してみましょう。
Rails 7 の初期画面が表示されればOKです!
簡単なCRUDアプリケーションを作成
scaffold で簡単な CRUD アプリケーションを作成
続いて、簡単な CRUD アプリケーションを作成してみましょう。
今回は scaffold というコマンドを使って、簡単に CRUD アプリケーションを作成します。
docker-compose run web rails g scaffold post title:string body:text
scaffold は、Rails でよく使われる機能のひとつで、 データベースのテーブルを作成し、そのテーブルに対応するモデルやコントローラ、ビューを一括で作成してくれます。
$ docker-compose run web rails g scaffold post title:string body:text
[+] Running 1/0
⠿ Container rails-docker-db-1 Running 0.0s
invoke active_record
create db/migrate/20230913232901_create_posts.rb
create app/models/post.rb
invoke resource_route
route resources :posts
invoke scaffold_controller
create app/controllers/posts_controller.rb
invoke tailwindcss
create app/views/posts
create app/views/posts/index.html.erb
create app/views/posts/edit.html.erb
create app/views/posts/show.html.erb
create app/views/posts/new.html.erb
create app/views/posts/_form.html.erb
create app/views/posts/_post.html.erb
invoke resource_route
invoke helper
create app/helpers/posts_helper.rb
データベースのマイグレーション
次に、データベースのマイグレーションを行います。
マイグレーションとは、データベースのテーブルを作成したり、 テーブルのカラムを追加したりするための仕組みです。
docker-compose run web rails db:migrate
以下のように表示されれば OK です。
$ docker-compose run web rails db:migrate
[+] Running 1/0
⠿ Container rails-docker-db-1 Running 0.0s
== 20230913232901 CreatePosts: migrating ======================================
-- create_table(:posts)
-> 0.0155s
== 20230913232901 CreatePosts: migrated (0.0155s) =============================
Rails サーバの再起動
最後に、Rails サーバを再起動しておきましょう。
docker-compose restart
CRUD アプリケーションの動作確認
では、実際にアプリを動かしてみましょう。
ブラウザのアドレスバーに http://localhost:3000/posts/new と入力し、起動を確認してみます。
以下のように、新規投稿画面が表示されるはずですので、こちらからポストを投稿できます。
また、投稿すると詳細ページにリダイレクトされて投稿内容が表示されていれば OK です。
後片付け – Dockerコンテナを削除
さて、動作確認ができて開発を始めることができましたが、もし開発を終えてコンテナを削除したい場合は以下のコマンドを実行するだけでOKです。
docker-compose down
docker-compose down
は、コンテナを停止して削除するコマンドです。
ちなみにコンテナを停止するだけであれば docker-compose stop
を使い、また開発をするときにdocker-compose up -d
でコンテナを起動しつつ、Rails サーバを起動できます。
補足:コンテナの起動に失敗した場合
もしコンテナの起動に失敗した場合は、以下のコマンドでログを確認してみましょう。
docker-compose logs
docker-compose logs
は、コンテナのログを確認するコマンドです。
コンテナのログを確認することで、どこでエラーが発生しているのかを確認することができます。
または、以下のコマンドでコンテナを削除してみましょう。
docker-compose down
先述の通り、docker-compose down
は、コンテナを停止して削除するコマンドです。
コンテナを削除することで、コンテナの状態をリセットすることができます。
そして、もう一度コンテナを起動してみましょう。
docker-compose up -d