【Docker、Rails】Rails＋MySQLの開発環境をDockerに移行

# 概要
Ruby on Rails ＋ MySQLで作成中のアプリの開発環境をDockerに移行しましたので、備忘録として記録します。

# 開発環境
macOS Big Sur バージョン 11.2.3
Ruby 2.6.5
Rails 6.0.3.4
MySQL 5.6.47

# 参照
## 1. 下準備

移行を実行する前に、Dockerの概念や使用方法をおおまかに把握しておいた方がよいです。本記事ではそれらについての説明は省略いたします。私は、以下の動画で学習しました。その他、書籍やwebサイトの情報もよさそうです。

https://www.udemy.com/course/rails-kj/

Railsの動作環境をDockerで構築する方法について体験できます。

https://www.udemy.com/course/docker-k/

GitHubやDocker Hubの設定画面等、やや情報が古い部分がありますので、それらはググる等して情報をアップデートしながら進めるとよいです。

## 2. 実行

以下2つのサイトのコードをほぼコピペして移行を実行することができました。

https://www.youtube.com/watch?v=Fq1PH0Gwi8I&t=216s

アプリ作成開始前にDockerで環境構築する方法は↑こちらの動画がわかりやすかったです。
Dockerfileやdocker-compose.ymlのコードは概要欄で公開されています。

https://qiita.com/majorboy/items/9fbfc78fc7bbc1f35e77

作成中のアプリをDockerに移行するにはコードを修正する必要があり、↑こちらの記事を参考にしました。
Docker環境のRailsアプリとSequelProを接続する方法についても記載されています。

# コード
コードの意味については上記の参照動画や記事をご覧ください。本記事では省略させていただきます。
アプリのルートディレクトリ直下に、Dockerfileとdocker-compose.ymlの2つのファイルを作成します。

```:Dockerfile
FROM ruby:2.6.5      # ← Rubyのバージョンは開発環境により異なります
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs

RUN mkdir /アプリ名
WORKDIR /アプリ名

COPY Gemfile /アプリ名/Gemfile
COPY Gemfile.lock /アプリ名/Gemfile.lock

RUN gem install bundler      # ← アプリ作成途中でDockerに移行する場合はこれがないとエラーが出るようです。
RUN bundle install
COPY . /アプリ名
```

```docker-compose.yml
version: "3"

services:
  db:
    image: mysql:5.6.47      # ← MySQLのバージョンは開発環境により異なります
    environment:
      MYSQL_USER: root
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "4306:3306"
    volumes:
      - ./db/mysql/volumes:/var/lib/mysql

  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/petput
      - gem_data:/usr/local/bundle
    ports:
      - 3000:3000
    depends_on:
      - db
    tty: true
    stdin_open: true

volumes:
  gem_data:
```

database.ymlに2つ追記します。

```database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password      # ← 追記
  socket: /tmp/mysql.sock
  host: db      # ← 追記
```

# Docker Composeのコマンド
ファイルの準備ができたら、アプリのルートディレクトリでDocker Composeのコマンドを実行します。

**コンテナをbuildする**

```:ターミナル
アプリ名 % docker-compose build
```

**コンテナ上でDBを作成し、migrationを実行**

```:ターミナル
アプリ名 % docker-compose run web rails db:create
アプリ名 % docker-compose run web rails db:migrate
```

**コンテナを起動**

```:ターミナル
アプリ名 % docker-compose up
```

コンテナが立ち上がれば、以下にアクセスすることでトップページが表示されます。
http://localhost:3000/

# docker-composeコマンド実行中に発生したエラーと解決法
## bundlerエラー

```:エラー文
#12 0.838 /usr/local/lib/ruby/2.6.0/rubygems.rb:283:in `find_spec_for_exe': Could not find 'bundler' (2.1.4) required by your /petput/Gemfile.lock. (Gem::GemNotFoundException)
#12 0.838 To update to the latest version installed on your system, run `bundle update --bundler`.
#12 0.838 To install the missing version, run `gem install bundler:2.1.4`
#12 0.839 	from /usr/local/lib/ruby/2.6.0/rubygems.rb:302:in `activate_bin_path'
#12 0.839 	from /usr/local/bin/bundle:23:in `<main>'
------
executor failed running [/bin/sh -c bundle install]: exit code: 1
ERROR: Service 'web' failed to build
```
上記の通り、`RUN gem install bundler`をDockerfileに追記したら解決できました。

参照：https://qiita.com/yosyosyoyoyo/items/407c22c0b1ba8e1dbded

## mimemagicエラー

```:エラー文
Your bundle is locked to mimemagic (0.3.5), but that version could not be found in any of the sources listed in your Gemfile. If you haven't changed sources, that means the author of mimemagic (0.3.5) has removed it. You'll need to update your bundle to a version other than mimemagic (0.3.5) that hasn't been removed in order to install.
```
ローカルで`bundle update minemagic`した後、`docker-compose build`を実行したら解決できました。

参照：https://akinov.hatenablog.com/entry/2021/03/26/085534

## yarnエラー

```:エラー文
warning Integrity check: System parameters don't match                                                                                                                                                 
error Integrity check failed                                                                                                                                                                           
error Found 1 errors.                                                                                                                                                                                  


========================================
  Your Yarn packages are out of date!
  Please run `yarn install --check-files` to update.
========================================


To disable this check, please change `check_yarn_integrity`
to `false` in your webpacker config file (config/webpacker.yml).


yarn check v1.17.3
info Visit https://yarnpkg.com/en/docs/cli/check for documentation about this command.
```

↓`check_yarn_integrity: false`としたら解決できました。

```webpacker.yml
# Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
check_yarn_integrity: false
```

参照：https://qiita.com/KenAra/items/2708ce3d5c80c4f24920

# おわりに
Dockerの概念や使用方法を理解するのが難しく、挫折しそうになりました。
実際に移行作業をする中で、特に以下のYouTube動画を見たあたりで理解が急激に進み、Docker開発環境を構築することができました。

https://www.youtube.com/watch?v=Fq1PH0Gwi8I&t=216s

**今回参照した動画や記事を作成された皆様に感謝いたします。**

以上、参考になりましたら幸いです。
間違いなどありましたら、ご指摘いただきたいです。

# 追記
開発環境をDockerに移行後、CapistranoでEC2へデプロイしようとしたら、`deploy:migrating`のところで`Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (2)`というエラーが発生しました。

本番環境のhost設定を指定したら解決できるかと考え、`database.yml`の`production`で`host: localhost`と指定しました。その後、**ローカルからGitHubにpushし、**`bundle exec cap production deploy`を実行したらデプロイできました。

```database.yml
production:
  <<: *default
  database: アプリ名_production
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock
  host: localhost      # ← 追記
```