Docker × Ruby on Rails × MySQLの環境構築


## Dockerのインストール
- [Install Docker Desktop for Mac](https://docs.docker.com/docker-for-mac/install/)
- [Install Docker Desktop for Windows](https://docs.docker.com/docker-for-windows/install/)

## RubyとMySQLのDockerイメージをダウンロード
```console
$ docker pull mysql:タグ名
$ docker pull ruby:タグ名
```
- 完了したら`Status: Downloaded newer image for [ダウンロード対象]`というメッセージが表示
- ダウンロードされたか`docker images`で確認

```console
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ruby                タグ名               f28a9e1d0449        4 days ago          868MB
mysql               タグ名               ba7a93aae2a8        2 weeks ago         372MB
```
- ダウンロードされていれば、上記内容が表示されるはず

## Dockerfile作成
```docker
FROM ruby:2.6.0
ENV LANG C.UTF-8
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN gem install bundler
WORKDIR /tmp
ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock
RUN bundle install
ENV APP_HOME /app_name
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
ADD . $APP_HOME
```
- **FROM**
    - 使用するイメージを指定。先ほどダウンロードしたRubyのイメージを指定。
- **ENV**
    - 環境設定。形式は、key-valueとなっている。
- **RUN**
    - 実行コマンド？ここに記載したコマンドは、ビルド時に実行される？
- **WORKDIR**
    - RUNやADDなどの命令実行対象ディレクトリを指定
- **ADD**
    - ファイルを追加する。形式は、ソース-送信先となっている
        - ソース
            - 追加したいファイルなどを指定
        - 送信先
            - どこにそのファイルなどを追加したいかを指定

- `apt-get update -qq`
    - **apt-get update**
        - パッケージリストの更新
    - **-qq**
        - エラー以外は表示しない

- `apt-get install -y build-essential libpq-dev nodejs`
    - **apt-get install**
パッケージをインストール
    - **-y**
        - 全ての問い合わせに Yes で答える
    - **build-essential**
        - 基礎開発ツール一式が格納されたパッケージ
    - **libpq-dev**
        - よくわからないが、何かしらが格納されたパッケージ
    - **nodejs**
        - サーバーサイドのJavaScript

### 参考
- [Dockerfile リファレンス](http://docs.docker.jp/engine/reference/builder.html)
- [apt-getコマンドを使う](http://www.ne.jp/asahi/it/life/it/linux/linux_command/linux_apt-get.html)
- [apt-get updateは何を行っているのか調べてみた〜パッケージインデックスファイルとは何か〜](http://karoten512.hatenablog.com/entry/2018/01/09/003330)
- [Bundlerとは？](https://qiita.com/io_fleming/items/14626a9cff44bc87e7db)
- [Dockerfileについて](https://qiita.com/tanan/items/e79a5dc1b54ca830ac21)

## Gemfile作成
```ruby
source 'https://rubygems.org'
gem 'rails'
```
- **source**
    - gemが置いてある場所を指定
- **gem**
    - gemコマンドで使用するgemを指定

### 参考
- [【初心者向け】GemfileとGemfile.lockの違い](https://nishinatoshiharu.com/difference-gemfile-gemfilelock/)
- [Gemfileについて調べてみた](http://xxxcaqui.hatenablog.com/entry/2013/02/11/013421)

## 空のGemfile.lock作成
```console
$ touch Gemfile.lock
```

- **Gemfile.lock**
    - Gemfileを元に実際にインストールされたgemに加え、依存関係にあるgemが記述されたファイル

## docker-compose.yml作成
```yaml
version: '2'
services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app_name
    ports:
      - "3000:3000"
    depends_on:
      - db
  db:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=password
```

- **version**
    - 任意の値で定義なしはversion: '1'という扱いになる
- **services**
    - バージョン2を指定した場合セットで定義
        - 以下にサービス内容を定義する
- **image**
    - 既存イメージを用いる場合指定
- **environment**
    - 環境変数などのexportをする
        - MySQLを使用する場合必須
- **command**
    - デフォルトコマンドの上書き
- **volumes**
    - マウント先指定
        - 形式は、[ホスト名:コンテナ]
            - 今回の場合だと、カレントディレクトリを**app_name**というディレクトリにマウントしている
- **ports**
    - ポートを指定
        - 形式は、[ホスト:コンテナ]
- **depends_on**
    - コンテナの作成順序と依存関係を決める

### 参考
- [Docker & Docker-Composeの基本的な使い方](https://qiita.com/koka/items/3d3d4ee5680f92a0ad89#docker-compose)
- [Docker Compose - docker-compose.yml リファレンス](https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa)
- [docker-compose depends_onとlinksの違い](https://qiita.com/sivertigo/items/9baa73d922a68788402b)

## Railsの雛形作成
```console
$ docker-compose run web rails new . --force --database=mysql --skip-bundle
```

- **web**のコンテナに対して、**rails new**で雛形作成
- **--force**
    - 既存のGemfileを書き換える
        - この後に再度ビルドし直す必要があるので、この時点では**--skip-bundle**でビルドをスキップする

## Gemfile編集
```ruby
gem 'therubyracer', platforms: :ruby
```

- **therubyracer**のコメントアウトを外す

### 参考
- [なぜRailsでtherubyracerのコメントを外さなきゃいけないのか](http://suu-g.hateblo.jp/entries/2012/12/22#20121222fn3)

## ビルドする
```console
$ docker-compose build
```

## database.ymlの編集
- 編集点
    - **password**
        - docker-compose.ymlの**MYSQL_ROOT_PASSWORD**と同じ値にする
    - **host**
        - docker-compose.ymlの**depends_on**と同じ値にする

※その他はRailsの雛形作成時に生成された内容で問題無いはず。

※編集後↓

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

## コンテナの実行
```console
$ docker-compose up -d
```

- **-d**
    - バックグラウンドで実行
        - この後model作成がある為、バックグラウンドで実行

## model作成
```console
$ docker-compose run web rake db:create
```

### You must use Bundler 2 or greater with this lockfile.が表示されたら…
- Bundlerのバージョン**2.0.1**が悪さをしている模様。根本原因は不明。
- 以下の手順で以前のバージョンを入れる
    - 1. **gemfile.lock**の中身全削除
    - 2. **$ gem install bundler -v バージョン**
        - 古いバージョンのBundlerのGem取得
    - 3. **$ bundler バージョン install**
        - Bundlerをインストール
    - 4. **docker-compose build**
        - ビルドし直す
    - 5. **$ docker-compose run web rake db:create**
        - 再度modelを作成する

#### 参考
[https://qiita.com/yoshijbbsk1121/items/87250501b32c6433943e](You must use Bundler 2 or greater with this lockfile.)

## ブラウザアクセス
- **localhost:3000**にアクセス

<img width="1440" alt="スクリーンショット 2019-02-24 14.27.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/267738/e815aa23-f529-ffd7-df5c-28bcdb518a3d.png">

# お疲れ様でした！！！

## おまけ
Twitterやってます！外部のエンジニアの方ともどんどん繋がりたいと考えていますので、是非フォローして頂ければと思います！[@Tatsuo96](https://twitter.com/Tatsuo96)
ブログ始めました！
https://note.mu/tatsuo_iriyama