docker-composeを使ってdocker化する方法(rails6×My SQL)

# 開発環境
* Mac (M1)
* Rails 6
* ruby 2.7.5
* mysql 12

# docker化する流れ
1\. 必要なファイルを準備

2\. コンテナイメージのビルド

3\. Rails プロジェクトを作成

4\. データベースの準備

5\. 必要なパッケージをインストール

6\. コンテナを起動

7\. 動作確認 

## 1\. 必要なファイルを準備

### 空ファイルの準備

まずは rails-docker ディレクトリローカルの中に
以下の 5 つの空ファイルを作成しましょう。

Dockerfile
docker-compose.yml
Gemfile
Gemfile.lock
entrypoint.sh

``` touch {Dockerfile,docker-compose.yml,Gemfile,Gemfile.lock,entrypoint.sh} ```
上記のコマンドを入力するとファイルが一気に作成できます。
作成できたら、Gemfile.lock 以外の 4 ファイルを編集していきます。

### Dockerfile　を編集

Docker では、 Dockerfile という名前のファイルで定義した通りに
コンテナイメージの作成が行われます。

そのため、Rails を動かすために必要なパッケージのインストール等は
この Dockerfile の中で指定することになります。

また、Dockerfile 内でベースとなるコンテナイメージを指定することも可能です。

今回は Ruby 2.7.5 を指定します。

Dockefile を以下のように編集してください。

####
```
FROM node:12.4-stretch as node

FROM ruby:2.7.5

# マルチステージビルドを利用したNode.jsのインストール

# Install Node.js and Yarn
ENV YARN_VERSION 1.16.0
RUN mkdir -p /opt
COPY --from=node /opt/yarn-v$YARN_VERSION /opt/yarn
COPY --from=node /usr/local/bin/node /usr/local/bin/
COPY --from=node /usr/local/lib/node_modules/ /usr/local/lib/node_modules/
RUN ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
  && ln -s /opt/yarn/bin/yarn /usr/local/bin/yarnpkg \
  && ln -s /usr/local/bin/node /usr/local/bin/nodejs \
  && ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
  && ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npx
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle update --bundler
RUN gem install bundler:1.17.2
RUN bundle install
COPY . /myapp
RUN bundle exec rails webpacker:install

# コンテナ起動時に実行させるスクリプトを追加
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Rails サーバ起動
CMD ["rails", "server", "-b", "0.0.0.0"] 
```


### docker-compose.yml　を編集

Rails を動かすコンテナサービス以外にも
MySQL (DB) を動かすコンテナサービスを起動し、サービス間での連携が必要な場合には
Docker Compose というツールを利用します。

Docker Compose は、複数のコンテナで構成されるアプリケーションについて
Docker イメージのビルドや、各コンテナの起動・停止といった管理を行うためのツールです。

Docker Compose では、Dockerビルドやコンテナ起動のオプションも含め
複数のコンテナのための定義を docker-compose.yml というファイルに記述することで、
Docker イメージのビルドやコンテナの起動を一括で行うことができるようになります

では、docker-compose.yml の中身を以下のように編集します。

db という欄で MySQL (DB) のコンテナサービス（以下、コンテナ）の起動に関する設定をし、
web という欄で Rails (アプリ) サービス起動に関する設定をしています。

#### docker-compose.yml
```version: '3'
services:
  db:
    image: mysql:5.7
    platform: linux/amd64
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "3306:3306"
    volumes:
      - ./tmp/db:/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:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```
### Gemfile の編集

#### Gemfile
```
source 'https://rubygems.org'
gem 'rails', '~> 6.1.4'
```
### entrypoint.sh の編集

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

rm -f /myapp/tmp/pids/server.pid

exec "$@"
```

これでスタート時点で必要なファイルは準備が完了しました。

## 2. コンテナイメージのビルド

早速コンテナイメージをビルドします。
```
$ docker-compose build
```

## 3. Rails プロジェクトを作成

次は docker-compose コマンドを使って rails new を実行し、
Rails プロジェクトを作成です。

docker-compose run に続けてサービス名を指定し、
さらにコンテナ内で実行したいコマンド（=railsコマンド) を続けていきます。

Rails が動くサービスには web という名前を docker-compose.yml で付けたので
コマンドでのコンテナ名としては web を当てはめます。

以下のコマンドを実行してください。
```
$ docker-compose run web rails new . --force --no-deps --database=mysql
```
rails new した時と同じように、ディレクトリ内に関連ファイルが生成されます。

## 4. データベースの準備

では次に、データベースの準備をしていきましょう。

まずは rails で使用しているデータベースファイルの設定を編集します。
config ディレクトリ内の database.yml というファイルが対象です。

下記のコードに全て変えてください。

#### config/database.yml

```
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  host: localhost

development:
  <<: *default
  database: myapp_development
  host: db
  username: root
  password: password

test:
  <<: *default
  database: myapp_test
  host: db
  username: root
  password: password
```

ポイントは、host の欄が db であることです。

db は docker-compose.yml で指定した MySQL のコンテナ名ですね。

同じ docker-compose.yml で指定したコンテナ間であれば、
コンテナ名をホストとして名前解決してアクセスすることができます。

さて、これで Rails がデータベースと連携できるようになったので
rails db:create コマンドを docker-compose 経由で実行して
データベースを作成しておきましょう。

```
$ docker-compose run web rails db:create
```

## 5. 必要なパッケージをインストール

Rails 6系からは Webpacker が必要となっているため
webコンテナ内に Webpacker をインストールしておきます。

これも rails コマンドから実行できます。

```
$ docker-compose run web rails webpacker:install
```

これで Rails サーバを起動させるための準備が整いました！

## 6. コンテナを起動

コンテナを起動するため、次のコマンドを実行します。

```
$ docker-compose up -d
```

docker-compose up は、コンテナ docker-compose.yml に基づいて起動するコマンドです。

コンテナ起動時にコンテナ内で実行させたいコマンド (= rails s) は
Dockerfile で設定しているので、
コンテナを起動させると Rails サーバが立ち上がります。

また、オプションの -d を付けるとバックグラウンドで起動させることができます。

## 7. ブラウザで動作確認

これで無事に Rails の開発用サーバが起動したことになります。

ブラウザのアドレスバーに http://localhost:3000/ と入力し、起動を確認してみましょう。

Yay!You're on rails!の画面が表示されれば完了です！