はじめに
バイト先で全面改修を進めていく上で、環境をdocker化しようという話が出ました。
フロントエンドNuxt.js、バックエンドRails6の構成で作ることになり、バックエンド部分を自分が担当することになったのでDockerfileをごりごり書いていきましょー!ということで勉強も兼ねて実装し、出来上がった構成を紹介します。
Railsコンテナの作り方は、Dockerの公式ページに簡単に書いてありますが、今回はRails6に考慮したDockerfileの書き方と、MySQLコンテナの作り方も合わせて紹介していこうと思います。
自身のスキル
個人でrailsを触り始めたのは1年半ほど前、webエンジニアとしての実務での開発経験は1年強と期間的には長くはありません。
しかし、大学でつけた幅広い前提知識や、どんどん色々なことに挑戦する姿勢を利用して素早く成長しています。
前のプロジェクトでもdocker周りには触らせていただいていて、データベースのコンテナの変更(MarinaDB->MySQL)や、初期設定用のシェルスクリプトの作成などを行っていました。
自分で1からdockerを作る機会がなかったので今回挑戦した形です。
docker環境作成
ここから先は実際にdockerによる環境を作っていきます。
ファイル構成
まずは簡単にファイル構成を紹介します。
作成するアプリケーションの名前をsample
とすると、今回関係するファイルは以下のようなファイル構成になっています。
sample
|- backend --- app
| |- bin
| |- config --- ...
| | |- database.yml
| | |- ...
| |- ...
| |- Dockerfile
| |- Gemfile
| |- Gemfile.lock
| |- ...
|- db --- data --- ...
| |- my.cnf
|- docker-compose.yml
実際はもっと多くのファイルが存在する(作成される)ことになりますが、今回操作するファイルはこれらのファイルのみになります。
必要ファイルの作成
続いてdockerに関するファイルを記述していきます。
backend/Dockerfile
これはRailsのコンテナをビルドするための手順を記したファイルになります。内容を下に載せ、それぞれどのような処理を行っているのかをコメントで説明しています。
# 使用するイメージとバージョン
FROM ruby:2.7.1
# 必要なライブラリをインストール
RUN apt-get update -qq && \
apt-get install -y build-essential \
libpq-dev \
nodejs
# 以下はrails6以降(APIモード除く)で必要
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn
# コンテナ内にappというフォルダを作成
# ※ローカルPCにフォルダが作成されるわけではない
RUN mkdir /app
# ルートをappディレクトリに変更
ENV APP_ROOT /app
WORKDIR $APP_ROOT
# ローカルPC内のGemfile(.lock)をコンテナ内にコピー
ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock
# bundle installを実行しローカルPCのファイルたちをコンテナ内にコピー
RUN bundle install
ADD . $APP_ROOT
# コンテナがlistenするポート番号
EXPOSE 3000
# 実行されるコマンド
CMD ["rails", "server", "-b", "0.0.0.0"]
rails6からはWebpackerがデフォルトとなったので、yarn
がインストールされていないとrails new
をするときにエラーとなってしまいます。
ただし、後述のAPIモードで作成する場合にはyarn
のインストールは不要です。
backend/Gemfile
RailsをインストーするためにあらかじめGemfile
を記述しておきます。
このファイルは後ほどrails new
をするときに書き換えられます。
ここではrails6以降のバージョンを指定しています。
source 'https://rubygems.org'
gem 'rails', '~> 6'
backend/Gemfile.lock
bundle install
した際に依存関係を元にライブラリの設計図のようなものを作ってくれます。
空のものを作成しておきます。ファイルが存在しないと後でエラーになりました。
db/data/
ディレクトリだけ用意しておいてあげましょう
db/my.cnf
MySQLの設定に関するファイルです。
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
sql_mode=''
[client]
default-character-set=utf8mb4
文字コードの設定やsql_mode
の設定を行っています。
特にsql_mode
の設定はしておいた方が良いと思います。
というのも、MySQL5.7からデフォルトのsql_mode
が変更となっており、特にonly_full_group_by
などのモードで度々エラーを吐いてしまうことがあるので、どのsql_mode
にするかは明示的に書いておきましょう。今回は設定なし(MySQL5.6.5以前のデフォルト)を明示的に指定しています。
(この辺りでも追々記事が書きたい)
docker-compose.yml
いよいよdocker-composeを書きます。
簡単な説明をコメントで記述してあります。
version: "3"
services:
# MySQL
db:
#ビルドするイメージ
image: mysql:5.7
# 環境変数の指定
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: spportunity
MYSQL_USER: root
MYSQL_PASSWORD: root
TZ: 'Asia/Tokyo'
# 文字コードをutf8mb4に設定
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
# db/dataディレクトリをコンテナのmysqlディレクトリにマウント
- ./db/data/:/var/lib/mysql
# /db/my.cnfファイルをコンテナ内のmy.cnf設定ファイルにマウント
- ./db/my.cnf:/etc/mysql/conf.d/my.cnf
ports:
- 3306:3306
#Rails
backend:
# ビルド元の指定
build:
context: ./backend
dockerfile: Dockerfile
# コンテナ名の指定
container_name: "sample-backend"
# 起動時のコマンド指定 前のプロセスを終了してからrails sをしている
command: bash -c "rm -f tmp/pids/server.pid && rails s -p 3000 -b '0.0.0.0'"
# backendフォルダ内のファイルをコンテナ内のappディレクトリにマウント
volumes:
- ./backend/:/app
ports:
- "3000:3000"
# dbコンテナよりも後に起動
depends_on:
- db
これでファイルの準備はできたのでrailsアプリケーションを作成していきます。
railsアプリケーションの作成
docker-compose
コマンドを利用してrailsアプリケーションを作成します。
現在のディレクトリがsample
であることを確認してください。
通常モードでrailsを作成(dockerfileでyarnのinstallが必要)
% docker-compose run backend rails new . --force --no-deps --database=mysql --skip-bundle
-
--force
...Gemfile
を書き換えます -
--database=mysql
...データベースにMySQLを指定します -
--skip-bundle
...bundle
をスキップします(まだGemfile.lock
は変更されません)
APIモードでrailsを作成
% docker-compose run backend rails new . --force --no-deps --database=mysql --skip-bundle --api
-
--api
...APIモードでの作成オプション
完了すると、backend/
フォルダ内にrails関連のフォルダやファイルが大量に出来上がります。
APIモードと通常モードの違いやファイルの差分はまた記事にします。
コンテナのビルド
% docker-compose build
このコマンドを実行することで、MySQLのコンテナの作成と、railsコンテナでのbundle install
が行われます。
コンソールを見ているとDockerfileの内容を順番に実行している様子が分かるかと思います。
railsのdbへの接続設定
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: root
host: db
development:
<<: *default
database: sample
test:
<<: *default
database: sample_test
production:
<<: *default
database: sample_production
username: <%= ENV['APP_DATABASE_USER'] %>
password: <%= ENV['APP_DATABASE_PASSWORD'] %>
接続情報を、hostを先ほど作成したMySQLコンテナのイメージ、ユーザー名とパスワードを先ほど作成したコンテナの環境変数のものに変更します。
(APIモードでなければ)Webpackerのインストール
% docker-compose run backend rails webpacker:install
データベースの作成
% docker-compose run backend rails db:create
dockerの起動
ここまで来れば設定は完了です。
あとはdockerを起動するのみです!
% docker-compose up
ブラウザでRailsが立ち上がっていること確認
ブラウザで http://localhost:3000/ へアクセスすると、無事Railsが立ち上がっています。
拡張性
今回は言及しませんでしたが、frontendコンテナなどを追加することによってフロントエンドアプリケーションとAPIサーバを兼ね備えた環境を一発で作ることができるようになります。
その際は、同様の手順でDockerfileの作成やdocker-composeへのコンテナの追加などを行っていくことになりまね。
僕はまだフロントエンド初心者なので、ゆくゆくはフロントのコンテナも作っていきたいです。
感想
やっぱりdockerは便利ですね。
自分個人の開発ではdockerは使っていませんでしたが、これからは積極的に使っていこうかなと思っています。
またその際には記事にしてあげていければと思います。
qiitaの記事を書くのが初めてで、どれくらいのものを書けばいいのか悩みながら書いていたら、だいぶ長くなってしまいました。
ただ、とても内容が濃い記事を何本も書いている人がたくさんいて、自分はまだまだだなぁと日々感じています。
僕はまだ内容があるものは頻繁には書けないかもしれませんが、少しずづ知識を記事化していければと思います。
参考にしたもの
以下のqiitaの記事を参考にさせていただきました。
書き方も真似させていただき、かなり参考になりました。
ありがとうございます。
https://qiita.com/azul915/items/5b7063cbc80192343fc0
https://qiita.com/kodai_0122/items/795438d738386c2c1966
上記の記事に加えて、APIモードやMySQLコンテナのマウントや設定なども盛り込んだ内容となっているので、書き方が似ている点はご容赦いただければと思います。