APIモードで作成したRails 6と、MySQL 8を組み合わせたDocker環境の構築手順について紹介します。
複数人でもスムーズに開発ができるようにするためリモートリポジトリからcloneしてきたらdocker-compose up
するだけでアプリケーションが立ち上がるという環境をゴールにします。
各種バージョンは以下の通りです。
- Ruby on Rails: 6.0.3.2
- Ruby: 2.7.1
- MySQL: 8.0.21
実行環境はDocker Desktop for Mac(バージョン 2.3.0.4)を利用しています。
目次
通常のRails 6 x MySQL 8のDocker環境との違い
前回チームで共有するための『Rails 6 x MySQL 8』Docker環境構築手順でRails 6とMySQL 8を組み合わせたDocker環境の構築手順について紹介しました。
前回の記事ではRails 6は通常モードで作成しました。
今回はRailsアプリケーションの構築にAPIモードを利用します。APIモードを利用する場合、以下の点が通常モードと異なります。
- rails newコマンドに『–api』オプションが必要になる
- Railsアプリケーションを起動する際にWebpackerが不要になるためNode.jsとYarnが不要になる
Railsアプリケーションの準備
今回はdocker-rails6-api-mysql8
というディレクトリにrails6_api_mysql8
という名前のアプリケーションを作成します。
ディレクトリの作成・移動をします。
$ mkdir docker-rails6-api-mysql8 && cd $_
rubyイメージを利用してローカル環境にGemfileを作成します。
$ docker run --rm -v `pwd`:/docker-rails6-api-mysql8 -w /docker-rails6-api-mysql8 ruby:2.7.1 bundle init
作成されたGemfileの『gem “rails”』をアンコメントし、railsのバージョンを指定します。
Gemfile
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
- # gem "rails"
+ gem "rails", '~> 6.0.3.2'
rails new
を実行するDocker環境を構築するためDockerfileを作成します。
APIモードでRailsアプリケーションを作成する場合、Node.js、Yarnの事前インストールは不要です。
Dockerfile
FROM ruby:2.7.1
# 作業ディレクトリを/rails6_api_mysql8に指定
WORKDIR /rails6_api_mysql8
# ローカルのGemfileをDokcerにコピー
COPY Gemfile* /rails6_api_mysql8/
# /rails6_api_mysql8ディレクトリ上でbundle install
RUN bundle install
Dockerfileをビルドして作成したイメージを利用してコンテナを起動し、コンテナ上でrails new
をします。
--api
のオプションを追加することでAPIモードのRailsアプリケーションを作成できます。
$ docker build -t rails6_api_mysql8 .
$ docker run --rm -v `pwd`:/rails6_api_mysql8 rails6_api_mysql8 rails new . --api –skip-bundle --database=mysql
docker-compose.yml
を作成します。
データベースの接続ユーザー名はwebuser
、パスワードはwebpass
としました。
データベースの情報はmysql_data
という名前付きボリュームを作成して永続化します。
docker-compose.yml
version: '3'
services:
api: # Ruby on Railsが起動するコンテナ
build: .
ports:
- '3000:3000' # localhostの3000ポートでアクセスできるようにする
volumes:
- .:/rails6_api_mysql8 # アプリケーションファイルの同期
depends_on:
- db
command: ["rails", "server", "-b", "0.0.0.0"]
db: # MySQLが起動するコンテナ
image: mysql:8.0.21
volumes:
- mysql_data:/var/lib/mysql # データの永続化
command: --default-authentication-plugin=mysql_native_password # 認証方式を8系以前のものにする。
environment:
MYSQL_USER: 'webuser'
MYSQL_PASSWORD: 'webpass'
MYSQL_ROOT_PASSWORD: 'pass'
MYSQL_DATABASE: 'rails6_api_mysql8_development'
volumes:
mysql_data: # データボリュームの登録
Ruby on Railsのデータベース接続設定を変更します。
config/database.yml
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: webuser
password: webpass
host: db # データベースのコンテナ名を指定する
Railsアプリケーションの起動確認
docker-compose up
を実行後、localhost:3000
にアクセスして以下の画面が表示されればOKです。
テスト環境用のデータベースの作成
development環境のデータベースが正常に作成されたため、Railsアプリケーションを起動できました。
しかし、test環境のデータベースはまだ用意されていないため、スクリプトを利用して用意します。
MySQLのDockerイメージでは/docker-entrypoint-initdb.d
にスクリプト(.sql
、.sh
、.sql.gz
)を配置しておくとコンテナ起動時に実行してくれるという機能があります。1
$ mkdir docker-entrypoint-initdb.d && cd $_
00_create.sql
-- test環境用のデータベースを作成する
CREATE DATABASE rails6_api_mysql8_test;
01_grant.sql
-- webuserという名前の一般ユーザーを利用する場合
GRANT ALL ON `rails6_api_mysql8_test`.* TO webuser@'%';
作成したスクリプトをコンテナ上で読み取れるようにするためバインドマウントを追加します。
version: '3'
services:
api: # Ruby on Railsが起動するコンテナ
build: .
ports:
- '3000:3000' # localhostの3000ポートでアクセスできるようにする
volumes:
- .:/rails6_api_mysql8 # アプリケーションファイルの同期
depends_on:
- db
command: ["rails", "server", "-b", "0.0.0.0"]
db: # MySQLが起動するコンテナ
image: mysql:8.0.21
volumes:
- mysql_data:/var/lib/mysql # データの永続化
+ - ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
command: --default-authentication-plugin=mysql_native_password # 認証方式を8系以前のものにする。
environment:
MYSQL_USER: 'webuser'
MYSQL_PASSWORD: 'webpass'
MYSQL_ROOT_PASSWORD: 'pass'
MYSQL_DATABASE: 'rails6_api_mysql8_development'
volumes:
mysql_data: # データボリュームの登録
git clone → docker-compose upで起動できるようにする
コンテナ起動時にマイグレーションを自動実行させることで、『git clone → docker-compose up』で環境が用意できるようにします。
マイグレーションを実行するスクリプトを作成します。
start.sh
#!/bin/bash -eu
rails db:migrate
rails server -b '0.0.0.0'
スクリプトのパーミッションを変更します。
$ chmod 755 start.sh
Rails側で行うdb:migrate
コマンドはMySQLコンテナの準備が完了してから実行する必要があります。
今回は、wait-for-it.shを利用してデータベースコンテナの準備完了を待つようにします。
wait-for-it.shをプロジェクトのルートディレクトリにコピーし、docker-compose.yml
を以下のように修正します。
docker-compose.yml
version: '3'
services:
api: # Ruby on Railsが起動するコンテナ
build: .
ports:
- '3000:3000' # localhostの3000ポートでアクセスできるようにする
volumes:
- .:/rails6_api_mysql8 # アプリケーションファイルの同期
depends_on:
- db
- command: ["rails", "server", "-b", "0.0.0.0"]
+ command: ["./wait-for-it.sh", "db:3306", "--", "./start.sh"]
db: # MySQLが起動するコンテナ
image: mysql:8.0.21
volumes:
- mysql_data:/var/lib/mysql # データの永続化
- ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
command: --default-authentication-plugin=mysql_native_password # 認証方式を8系以前のものにする。
environment:
MYSQL_USER: 'webuser'
MYSQL_PASSWORD: 'webpass'
MYSQL_ROOT_PASSWORD: 'pass'
MYSQL_DATABASE: 'rails6_api_mysql8_development'
volumes:
mysql_data: # データボリュームの登録
まとめ
以上でAPIモードのRails 6と、MySQL 8を組み合わせたDocker環境の構築手順について紹介を終わります。
環境構築の詳細については前回紹介したチームで共有するための『Rails 6 x MySQL 8』Docker環境構築手順で説明をしていますので、そちらの記事もあわせて参考にしていただければと思います。
この記事がいいなと思いましたらTwitter(@nishina555)のフォローもよろしくお願いします!