Dockerを使ったRuby on Rails + MySQLの環境構築手順

## `Docker`,`Rails`,`MySQL`の環境構築手順の記録

Railsのデフォルトホーム画面を表示させるところまで。

**環境**

* Windows10
* Ruby2.7.1
* Rails6.0.3.1
* MySQL8.0

### １．Docker for Windowsをインストール
https://hub.docker.com/editions/community/docker-ce-desktop-windows/
上記リンクにアクセスしてインストールする。
インストールが出来たら一度再起動してから、Dockerを起動させる。

### ２．必要ファイルの作成
任意の場所にディレクトリを作成する。

次にVScodeで作成したディレクトリを開く。
インストールがまだの場合は以下リンクからインストール
https://azure.microsoft.com/ja-jp/products/visual-studio-code/

* **Dockerfileの作成**

VScodeでディレクトリを開けたらディレクトリ内に`Dockerfile`を作成し、
以下のように記述する。

```Dockerfile
FROM ruby:2.7
RUN apt-get update -qq && apt-get install -y nodejs yarnpkg
RUN ln -s /usr/bin/yarnpkg /usr/bin/yarn
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
```

* **Gemfileの作成**

次に同じ階層に`Gemfile`を作成し、以下のように記述する。

```Gemfile
source 'https://rubygems.org'
gem 'rails', '~>6'
```

もう一つ`Gemfile.lock`というファイルを作成する。
中身は空でOK。

* **entrypoint.shの作成**

次に`Dockerfile`の中で`ENTRYPOINT`として定義している`entrypoint.sh`の作成する。

```entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /app/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
```

* **docker-compose.ymlの作成**

最後に`docker-compose.yml`というファイルを同階層に作成し、以下を記述。

```docker-compose.yml
version: '3'
services:
  db:
    image: mysql:8.0
    volumes:
      - ./tmp/db:/var/lib/mysql
    environment:
      - MYSQL_ALLOW_EMPTY_PASSWORD=1
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db
```

`MYSQL_ALLOW_EMPTY_PASSWORD`を設定することでpasswordが空でもrootで接続できるようにしておく。

### ３．Rails new / docker-compose buildを行う

VScodeのターミナルを開き、作成したディレクトリの階層にいる事を確認したら、
以下を実行する。

```
$ docker-compose run web bundle exec rails new . --force --database=mysql
```

`--force`は既存のファイルを上書き、`--database`でMySQLを指定しています。
実行完了したらビルドを行います。

```
$ docker-compose build
```

### ４、DBのホスト名の変更 / docker-compose upを行う

現状だとデータベースへの接続が出来ないので、
最初に作成したディレクトリ内に出来た`config/database.yml`の`host`の値を`db`という値に置き換える。

```database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  host: db
development:
  <<: *default
  database: app_development
test:
  <<: *default
  database: app_test
```

ここの`db`がコンテナ名になります。

これが出来たら再度`docker-compose build`を行ってから`docker-compose up`を行う。
この状態で`localhost:3000`に接続するとおそらくエラーが出る。
Webコンテナがmysql8.0の`caching_sha2_password認証方式`に対応していない為。
次の手順で認証方式を`mysql_native_password`に変更する。

### ５．MySQLの認証方式の変更

まずDBコンテナに入ります。
（VScodeで`docker-compose up`を行っていると思うので、powershellを使って該当のディレクトリを開いてください。）
そこでbashを起動します。

```
docker-compose exec db bash
```

その後、mysqlコマンドで接続します。

```
mysql -u root
```

場所が`mysql>`になっている事を確認したら、
下記のクエリを実行する。

```
mysql> select User,Host,plugin from mysql.user;
```

すると以下のようなユーザ一覧と認証方式が出てくる。

```
+------------------+-----------+-----------------------+
| User             | Host      | plugin                |
+------------------+-----------+-----------------------+
| root             | %         | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)
```

上記で出てきた`root`の`plugin`にある`caching_sha2_password`を`mysql_native_password`に変更します。
今回対象のroot@%のユーザ設定を`ALTER USER`を使って変更します。
下記のクエリを実行する。

```
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '';
```

実行出来たら改めて`select User,Host,plugin from mysql.user;`を実行すると、

```
+------------------+-----------+-----------------------+
| User             | Host      | plugin                |
+------------------+-----------+-----------------------+
| root             | %         | mysql_native_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)
```

上記のような表示に変わっている。

その後`exit`を2回実行して、元いた階層に戻る。
階層が作成したディレクトリなのを確認出来たら以下を実行。

```
$ docker-compose exec web bundle exec rails db:prepare
```

### ６．Railsのホーム画面にアクセス

DBを作成し、`localhost:3000`すると、Railsのホーム画面にアクセスできるようになる。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3633323637382f62656437383438352d623431632d343834632d656435332d6438323433643938383737312e706e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1315836/69abb3f5-5e56-f4e8-479f-4efd7b7d328c.png)

終了。