APIモードで作成する『Rails 6 x MySQL 8』Docker環境構築手順

インフラ

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 x 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: # データボリュームの登録

【Docker】Railsで理解する、複数のMySQLデータベースに一般ユーザーで接続するための環境構築手順

Dockerのデータを永続化!Data Volume(データボリューム)の理解から始める環境構築入門

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@'%';

【Docker】Railsで理解する、複数のMySQLデータベースに一般ユーザーで接続するための環境構築手順

作成したスクリプトをコンテナ上で読み取れるようにするためバインドマウントを追加します。

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)のフォローもよろしくお願いします!