【Rails6】Docker+Rails6+puma+nginx+mysql【環境構築＊初心者必見】

##本記事の目的
本記事では**Dockeを用いてRails6の環境構築を行うこと**を目的としています。
Rails6では**yarnというjsのパッケージ管理ツールとwebpackerがデフォルト**となっているので、Rails5の手順で環境構築を行うとエラーが出てしまいます。
よって本記事ではRails6対応の環境構築を目的としています。

※Dockerそのものについてはあまり触れませんので、Docker基礎を学習してからの方が良いかもしれません。

##ディレクトリ構成
環境構築する際の全体の構成を以下に示します。
ここでは「webapp」というファイルを作成してアプリケーションを作っていきます。

```言語:全体構成
/webapp
├── containers
│   └── nginx
│       ├── Dockerfile
│       └── nginx.conf
├── docker-compose.yml
├── Dockerfile
├── environments
│   └── db.env
├── Gemfile
└── Gemfile.lock
```
##Dockerfile（Rails用)
Rails用のDockerfileは以下のように記述します。
Rubyのバージョンは2.7.1を用います。

ここでのポイントは、**yarnとNode.jsのインストールコマンドを書いている点**です。

また、本記事ではNodeのバージョンを現時点での最新14.0を使っています。
もし、アプリケーションを作成した時に「Nodeをアップグレードしてください」と出た場合、setup_14〜の数字を最新のバージョンに変えてみてください。

```言語:Dockerfile
FROM ruby:2.7.1

# リポジトリを更新し依存モジュールをインストール
RUN apt-get update -qq && \
    apt-get install -y build-essential \
                       nodejs

# yarnパッケージ管理ツールインストール
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

# Node.jsをインストール
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
    apt-get install -y nodejs

# ルート直下にwebappという名前で作業ディレクトリを作成（コンテナ内のアプリケーションディレクトリ）
RUN mkdir /webapp
WORKDIR /webapp

# ホストのGemfileとGemfile.lockをコンテナにコピー
ADD Gemfile /webapp/Gemfile
ADD Gemfile.lock /webapp/Gemfile.lock

# bundle installの実行
RUN bundle install

# ホストのアプリケーションディレクトリ内をすべてコンテナにコピー
ADD . /webapp

# puma.sockを配置するディレクトリを作成
RUN mkdir -p tmp/sockets
```

##Gemfile
インストールするRailsのバージョンを指定します。
Rails6に対応するように書いています。

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

##Gemfile.lock
こちらはファイルの作成のみでOKで、中身は書かなくて構いません。

##Dockerfile(Nginx)

```言語:Dockerfile
FROM nginx:1.15.8

# インクルード用のディレクトリ内を削除
RUN rm -f /etc/nginx/conf.d/*

# Nginxの設定ファイルをコンテナにコピー
ADD nginx.conf /etc/nginx/conf.d/webapp.conf

# ビルド完了後にNginxを起動
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
```

##Nginx設定ファイル

```言語:nginx.conf
# プロキシ先の指定
# Nginxが受け取ったリクエストをバックエンドのpumaに送信
upstream webapp {
  # ソケット通信したいのでpuma.sockを指定
  server unix:///webapp/tmp/sockets/puma.sock;
}

server {
  listen 80;
  # ドメインもしくはIPを指定
  server_name example.com [or 192.168.xx.xx [or localhost]];

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  # ドキュメントルートの指定
  root /webapp/public;

  client_max_body_size 100m;
  error_page 404             /404.html;
  error_page 505 502 503 504 /500.html;
  try_files  $uri/index.html $uri @webapp;
  keepalive_timeout 5;

  # リバースプロキシ関連の設定
  location @webapp {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://webapp;
  }
}
```

##DB情報ファイル
ここでのユーザー名やパスワードは変更して構いません。

```言語:db.env
MYSQL_ROOT_PASSWORD=db_root_password
MYSQL_USER=user_name
MYSQL_PASSWORD=user_password
```

##docker-compose.yml

```言語:docker-vcompose.yml
version: '3'
services:
  app:
    build:
      context: .
    env_file:
      - ./environments/db.env
    command: bundle exec puma -C config/puma.rb
    volumes:
      - .:/webapp
      - public-data:/webapp/public
      - tmp-data:/webapp/tmp
      - log-data:/webapp/log
    depends_on:
      - db
  db:
    image: mysql:5.7
    env_file:
      - ./environments/db.env
    volumes:
      - db-data:/var/lib/mysql
  web:
    build:
      context: containers/nginx
    volumes:
      - public-data:/webapp/public
      - tmp-data:/webapp/tmp
    ports:
      - 80:80
    depends_on:
      - app
volumes:
  public-data:
  tmp-data:
  log-data:
  db-data:
```

##Railsの生成（Rails new)
Dockerコンテナ内でRailsを生成しなければいけないので、docker-compose run コマンドを使います。
ここではGemをインストールしません。

```
$ docker-compose run --rm app rails new . --force --database=mysql --skip-bundle
```

##puma.rbの編集
先ほどのコマンドで生成されたpuma.rbファイルを以下のように編集します。

```言語:puma.rb
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart

app_root = File.expand_path("../..", __FILE__)
bind "unix://#{app_root}/tmp/sockets/puma.sock"

stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true
```

##database.ymlの編集
Railsはデフォルトで、localhost上でDBが動作するようになっているので、hostを先ほど作成したdbに変更します。
また、ここにおける「MYSQL_USER」 と「 MYSQL_PASSWORD」 は DBファイルで定義した環境変数名を設定してくだい。

```言語:database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch('MYSQL_USER') { 'root' } %>
  password: <%= ENV.fetch('MYSQL_PASSWORD') { 'password' } %>
  host: db

development:
  <<: *default
  database: webapp_development

test:
  <<: *default
  database: webapp_test
```
##イメージのビルド
docker-compose.ymlで、app・db・webのbuildに指定されているDockerfileを元にイメージを作成します。

```
$ docker-compose build
```

##コンテナ起動
ビルドが完了しイメージができたら以下のコマンドでコンテナを立ち上げます

```
$ docker-compose up -d
```
ここでコンテナが起動しているのかを以下のコマンドを入力して確認します。

```
docker-compose ps
```

そうすると以下のようにコンテナの状況が見れると思います。

```
    Name                  Command               State          Ports       
---------------------------------------------------------------------------
webapp_app_1   bundle exec puma -C config ...   Up                         
webapp_db_1    docker-entrypoint.sh mysqld      Up      3306/tcp, 33060/tcp
webapp_web_1   /bin/sh -c /usr/sbin/nginx ...   Up      0.0.0.0:80->80/tcp 
```

#webpackerのインストール
起動したコンテナ内でwebpackerをインストールするので、以下のコマンドでインストールします。
Dockerfileになにかしら記入すれば、いちいちコマンドを入力しなくても良いとは思いますが、今回はこの方法を用います。

```
docker-compose exec app rails webpacker:install
```

以下のメッセージが出現すればインストール完了です。

```
Webpacker successfully installed 🎉 🍰
```

##DBの作成
DBの作成は必須なので、コンテナ内でDBを作成します。

```
docker-compose exec app rails db:create
```

##確認
以下のリンクをクリックして「You're on Rails」が表示されるか確認しましょう。
http://localhost
上手くいけば、Rails6で起動できていることが分かるかと思います。

<img width="1369" alt="スクリーンショット 2020-06-02 14.03.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618902/d42f458f-a6ba-bf06-7371-d8eeec5e43de.png">

#補足
localhostに変更内容が反映されていなくて、思うような結果が得られなければ、一度コンテナを閉じて、再起動させるのがいいでしょう。

```言語:コンテナ終了
docker-compose down
```

```言語:コンテナ起動
docker-compose up 
```

##参考サイト
以下の記事を参考にしながら環境構築をしました。
本記事だけでなく、以下のサイトも確認してみてください。

[①Docker + Rails + Puma + Nginx + MySQL](https://qiita.com/eighty8/items/0288ab9c127ddb683315#%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3)
[②DockerでRuby on Railsの環境構築を行うためのステップ【Rails 6対応】](https://qiita.com/kodai_0122/items/795438d738386c2c1966#1-3-gemfile-%E4%BD%9C%E6%88%90)
[③[Docker] Node.js以外のコンテナに追加でNode.jsの最新版をインストールするDockerfileの記述](https://qiita.com/jshimazu/items/c484c6b5acd1ca11e05d)