Railsアプリの開発環境をDockerに移行する手順(Rails5 + MySQL8.0 + docker-compose)

# はじめに
Dockerを全く知らない実務未経験の筆者が、自作したRailsアプリの開発環境をDockerに移行するまでをまとめました。

移行までの期間は基礎的な学習含めて一週間ほどでした（エラーがなければ半分ぐらいでできたかも...）

Dockerを触ってみたい、エラーに詰まっているという方の参考になれば嬉しいです。


# 環境
+ Mac OS
+ Ruby2.5.1
+ Rails5.2.4
+ MySQL8.0（※）

**※注意！**
MySQLは5.0系と8.0系でデフォルトの認証形式が異なります。(2020/8/18現在)
その影響で**バージョンによってDockerを作成するのに必要なファイル(docker-compose.yml)の記述が異なります。**
そのため自分が使っているMySQLのバージョンと、文献で書かれているMySQLのバージョンが合っているかご確認ください。


# 基礎学習
教材：[入門ドッカー](https://y-ohgi.com/introduction-docker/)

[入門ドッカー](https://y-ohgi.com/introduction-docker/)はハンズオン形式で学習できる無料サイトで、Dockerに関する用語や構造について簡単に学習できます。

Dockerについて何も知らない方は、全ての内容をやっても半日〜1日くらいで終わるので、[入門ドッカー](https://y-ohgi.com/introduction-docker/)でざっくり勉強することをおすすめします。


# 前提

+ 既存のRailsアプリケーションがある
+ 開発環境・及びテスト環境をDockerに移行する


# Dockerを使う上で必要なファイル

既存のアプリケーションに追加するファイルと修正が必要なファイルは以下の三つです。

+ **Dockerfile**
+ **docker-compose.yml**
+ **database.yml**

ファイル構成は以下の通りになります。

```
sampleApp ---- Dockerfile #追加するファイル
           |-- docker-compose.yml  #追加するファイル
           |-- Gemfile
           |-- Gemfile.lock
           |-- README.md
           |-- Rakefile
           |-- app
           |-- bin
           |-- config ---- application.rb
           |           |-- boot.rb
           |           |-- cable.yml
           |           |-- credentials.yml.enc
           |           |-- database.yml　　　　　#修正するファイル
           |           |-- environment.rb
           |           |-- environments
           |           |-- initializers
           |           |-- locales
           |           |-- master.key
           |           |-- puma.rb
           |           |-- routes.rb
           |           |-- spring.rb
           |           |-- storage.yml
           |
           |-- config.ru
           |-- db
           |-- lib
           |-- log
           |-- package.json
           |-- public
           |-- storage
           |-- test
           |-- tmp
           |-- vendor
```

## Dockerfile

```dockerfile:Dockerfile

#Docker Image を指定します。使用しているアプリのバージョンを指定します。
FROM ruby:2.5.1　

# 必要なパッケージのインストール。node.jsについては当初の記述だとエラーが出たため、修正。
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - && apt-get update && apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y mysql-client --no-install-recommends && rm -rf /var/lib/apt/lists/*

# 作業ディレクトリの作成、設定
RUN mkdir /workdir
WORKDIR /workdir

# ホスト側（ローカル）のGemfileを上記で作成した/workdirに追加する
ADD Gemfile /workdir/Gemfile
ADD Gemfile.lock /workdir/Gemfile.lock

# Gemfileのbundle install　
# ENVなしで実行したところエラーが出た。BUNDLER_VERSIONを指定することで回避。
ENV BUNDLER_VERSION 2.1.4
RUN gem install bundler
RUN bundle install

# ホスト側（ローカル）の全てのディレクトリをDocekrコンテナの/workdir配下に追加。
ADD . /workdir
```


## docker-compose.yml


```yml:docker-compose.yml

# docker-composeのバージョンを指定します。今回は'3'を使用。
version: '3'

# 起動するコンテナの定義を行います。このファイルではdb, db-test , webの三つを定義しています。 
services:
  db:
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password　# デフォルトの認証形式をmysql_native_passwordに変更。MySQL5.0系なら不要。
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: appname_development
      MYSQL_USER: yuki #任意のユーザー
      MYSQL_PASSWORD: password
      TZ: Asia/Tokyo
    volumes:
      - ./mysql/mysql_data:/var/lib/mysql
      - ./logs:/var/log/mysql
      - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    ports:
      - "4306:3306"

  db-test:
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: appname_test
      MYSQL_USER: yuki
      MYSQL_PASSWORD: password
      TZ: Asia/Tokyo
    volumes:
      - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    tmpfs:
      - /var/lib/mysql
      - /var/log/mysql
      
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: /bin/sh -c "rm -f /workdir/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    tty: true
    stdin_open: true
    depends_on:
      - db
    ports:
      - "3000:3000"
    volumes:
      - .:/workdir

```


## database.yml


```yml:database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: appname_development
  username: yuki
  password: password
  host: db
  socket: /tmp/mysql.sock

test:
  <<: *default
  database: appname_test
  host: db-test
  username: yuki
  password: password
  socket: /tmp/mysql.sock

production:
  <<: *default
  database: <%= ENV['DB_NAME'] %>
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>
  host: <%= ENV['DB_HOSTNAME'] %>

```

# Docker起動・DB作成

```terminal:
$ docker-compose build # コンテナをビルド
$ docker-compose up -d # コンテナの一斉起動

$ docker-compose run web bundle exec rake db:create  #DB作成
$ docker-compose run web bundle exec rake db:migrate #マイグレーション
```


ここまでできれば http://localhost:3000 にてアクセス出来るはずです。