[Rails+Vue.js]に係るCRUD入門〜Part Last: Docker化編〜

Rails+Vue.js+Webpackerによる「Create, Read, Update, Destroy」処理のチュートリアルを記述する...
~~しかし、半年前にあらかた学びたいことは終わり、業務では Nuxt を見ることが多くなるため、シリーズとして終了とする。~~

# ＜概要＞
## □ 本記事の内容
- 開発環境を Docker 化する。
- 合わせて Ruby と Rails のバージョンを上げる。
- 今回のコードは，[GitHubのコミット履歴](https://github.com/masayuki-0319/rails-vue-bookshelf/commits/07/setting_docker)で確認可能である。

## □ 記事共通
- 目次
    - [ソースコード(GitHubへリンク)](https://github.com/masayuki-0319/rails-vue-bookshelf)
    - [〜Part１: 環境構築編](https://qiita.com/Moo_Moo_Farm/items/afacfe4349af6a106253)
    - [〜Part２: Read編](https://qiita.com/Moo_Moo_Farm/items/fdf133d4c2bcf6d207b6)
    - [〜Part３: Vue Router設定編](https://qiita.com/Moo_Moo_Farm/items/075e970287cb1aaf52c1)
    - [〜Part４: Create, Update, Delete編](https://qiita.com/Moo_Moo_Farm/items/8cf46e228d59417550b1)
    - [〜Part５: Vuex設定編](https://qiita.com/Moo_Moo_Farm/items/fbc2e8c8f971dc5fe4bb)
    - [〜Part６: ユーザー登録&ログイン編](https://qiita.com/Moo_Moo_Farm/items/65aaa2ac7f8cef50fca6)
    - [▲ Part Last: Docker化編](https://qiita.com/Moo_Moo_Farm/items/5975cd9d2d48ee35d6d6)
- 実装機能
    - お気に入りの本に係る登録，参照，編集，削除処理
    - 非同期通信（Ajax）による[Rails+Vue.js]のCRUD処理
    - Single Page Application（SPA）
    - ユーザー登録機能（JWTによるトークン認証）
    - 開発環境をDocker化

- 開発環境
    - MacOS Mojave
    - Ruby(2.5.1 => 2.7.0)
    - Ruby on Rails(5.2.1 => 6.0.1)
    - Vue.js(2.6.10)
    - Yarn(1.17.0)
    - Webpack(4.39.2)

- 学習情報URL
    - [Vue.js公式](https://jp.vuejs.org/)
    - [Vue Mastery(The Vue Instance)](https://www.vuemastery.com/)

# ＜本文＞

## □ 各種ファイルの調整

### ■ Ruby, Rails のバージョンアップ関係


```diff:application.rb

...
- config.load_defaults 5.2
+ config.load_defaults 6.0
+ config.time_zone = "Asia/Tokyo"

...
```

```diff:Gemfile

...
- ruby '2.5.1'
+ ruby '2.7.0'

...
- gem 'rails', '~> 5.2.3'
+ gem 'rails', '6.0.2'

...
- gem 'sqlite3'
+ gem 'mysql2'
```

```Gemfile.lock
# 全削除
```

### ■ Docker化: サーバ起動設定


```bash:bin/server
#!/bin/ash -i
rm -f /app/tmp/pids/server.pid
bundle exec foreman start -f Procfile.dev
```

```dev:Procfile.dev
web: bundle exec rails s -p 5000 -b 0.0.0.0
webpacker: ./bin/webpack-dev-server --host 0.0.0.0 --port 3035
```

```diff:config/webpakcer.yml

...

	dev_server:
    https: false
-   host: localhost
+   host: 0.0.0.0
    port: 3035
-   public: localhost:3035
+   public: 0.0.0.0:3035

...
```

### ■ Docker化: mysql の接続設定

```yml:config/database.yml
default: &default
  adapter: mysql2
  charset: utf8mb4
  collation: utf8mb4_bin
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: <%= ENV.fetch("APP_DATABASE_HOST") { '127.0.0.1' } %>
  port: <%= ENV.fetch("APP_DATABASE_PORT") { '3306' } %>
  username: <%= ENV.fetch("APP_DATABASE_USERNAME") { 'root' } %>
  password: <%= ENV.fetch("APP_DATABASE_PASSWORD") { 'pass' } %>

development:
  <<: *default
  database: rails_vue_bookshelf_development

test:
  <<: *default
  database: rails_vue_bookshelf_test

production:
  <<: *default
  database: rails_vue_bookshelf_production
```


### ■ Docker化: redis の接続

```ruby:config/initializers/redis.rb
# docker-compose.yml で定義する `REDIS_URL: redis://redis:6379`が入る。
REDIS ||= Redis.new(url: ENV['REDIS_URL'] || 'redis://localhost:6379')
```

```diff:books_controller.rb
# 'json'の箇所を全てシンボルに置換する。
# Rails6へのバージョンアップによりシンボルしか受け付けなくなったみたい。

... 
- render 'index', formats: 'json', handlers: 'jbuilder'
+ render 'index', formats: :json, handlers: 'jbuilder'

...
- render 'show', formats: 'json', handlers: 'jbuilder'
+ render 'show', formats: :json, handlers: 'jbuilder'

...
- render 'index', formats: 'json', handlers: 'jbuilder'
+ render 'index', formats: :json, handlers: 'jbuilder'

...
```


## □ Docker 化の実行
### ■ Dockerfile の準備

```bash:bash
$ mkdir docker
$ touch docker/Dockerfile
```

```Dockerfile:Dockerfile
FROM ruby:2.7.0-alpine3.10
ENV LANG C.UTF-8
ENV TZ Asia/Tokyo

ENV BASE_PACKAGES="alpine-sdk build-base tzdata" \
    WEBPACKER_PACKAGES="python2 yarn nodejs-current nodejs-npm" \
    BUILD_PACKAGE="mysql-client mysql-dev" \
    FAVORITE_PACKAGE="less"

RUN apk update && \
    apk upgrade && \
    apk --update --no-cache add \
        ${BASE_PACKAGES} \
        ${WEBPACKER_PACKAGES} \
        ${BUILD_PACKAGE} \
        ${FAVORITE_PACKAGE}

WORKDIR /app

COPY Gemfile \
     Gemfile.lock \
     package.json \
     yarn.lock \
     /app/

RUN bundle install --jobs=4

RUN yarn install

# https://github.com/bundler/bundler/issues/6154
ENV BUNDLE_GEMFILE='/app/Gemfile'
```

### ■ docker-compose.yml の準備

```bash:bash
$ touch docker-compose.yml
```

```yml:docker-compose.yml
version: '3'
services:
  datastore:
    image: busybox
    volumes:
      - db_data:/var/lib/mysql
      - redis_data:/data
      - bundle_install:/usr/local/bundle
      - node_modules:/app/node_modules
  db:
    image: mysql:5.7
    ports:
      - 3306:3306
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: pass
  app:
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    command: ["bin/server"]
    ports:
      - 5000:5000
      - 3035:3035
    volumes:
      - bundle_install:/usr/local/bundle
      - node_modules:/app/node_modules
      - ./:/app:cached
    environment:
      APP_DATABASE_HOST: db
      APP_DATABASE_USERNAME: root
      APP_DATABASE_PASSWORD: pass
      REDIS_URL: redis://redis:6379
    depends_on:
      - db
      - redis
    stdin_open: true
    tty: true
  redis:
    image: redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    stdin_open: true
volumes:
  db_data:
  redis_data:
  bundle_install:
  node_modules:
```


### ■ その他設定

- ご覧通りデータベースの初期設定に必要なコード群です。
- `$ docker/bootstrap`で一括で必要なコマンドを実行してもらうことが目的です。

```bash:bash
$ touch docker/bootstrap
$ chmod 777 docker/bootstrap
```

```bash:docker/bootstrap
#!/usr/bin/env bash

docker-compose run --rm app ./bin/rails db:create
docker-compose run --rm app ./bin/rails db:migrate
docker-compose run --rm app ./bin/rails db:seed
```


### ■ コンテナの構築及び起動

- 以下を実行して http://localhost:5000 で起動を確認したら成功です。


```bash:bash
$ ./docker/bootstrap
$ docker-compose build
$ docker-compose up -d
```

**〜Part Last: Docker化編終了〜**