[Rails] DockerでRails + MySQLの開発環境をつくる手順

※ 2017/11/19 追記
dbのdataファイルをマウントするのを忘れていたので追記しました。

# MacのローカルにRails開発環境作るのがつらくなってきた

MacのローカルにRails開発環境を構築していると

* OSやグローバルライブラリのアップデートの度にGem Installでエラーが起こったりして焦る
* DBの設定はプロジェクトごとで変えたい（複数DBサーバーを起動したい）
* 運用環境はLinuxなので, Mac依存の設定をしている時間がもったいない

などのストレスに悩まされます。
Dockerで開発環境をつくれば、プロジェクトごとに分離されたLinux環境を構築でき、
上記のストレスから開放されるので非常におすすめです。

# 構築手順

参考：
https://docs.docker.com/compose/rails/#connect-the-database

※ Docker for Macをインストール済みの前提です。
https://www.docker.com/docker-mac

## projectのルートディレクトリを作成（新規プロジェクトの場合のみ）

```
$ mkdir myapp
```

`rails new` はここではせず、あとでdockerコンテナ作成後に行う。

## 1. Dockerfileを作成

```:Dockerfile
FROM ruby:2.4.2
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
```

## 2. Gemfileと空のGemfile.lockを作成（新規作成の場合のみ）

```:Gemfile
source 'https://rubygems.org'
gem 'rails', '5.1.4'
```

```
$ touch Gemfile.lock
```

## 3. docker-compose.yml を書く

```:docker-compose.yml
version: '3'
services:
  db:
    image: mysql
    environment:
      MYSQL_USER: root
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3316:3306'
    volumes:
      - ./db/mysql/volumes:/var/lib/mysql
    

  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```

## 4. rails new でDockerコンテナの中にスケルトン作成（新規プロジェクトの場合のみ）

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

docker-compose.ymlの `volumes: - .:/myapp` の部分でdockerとローカルのディレクトリを同期するように設定しているため、このコマンドを実行後、同時にローカルにも同様のファイルが生成される。 

## 5. rails new で新しく追加されたgemをinstallするため、イメージを再ビルド（新規プロジェクトの場合のみ）

```
$ docker-compose build
```

## 6. database.ymlの設定

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

docker-compose.ymlで `MYSQL_ROOT_PASSWORD` で設定したパスワードを設定する
また、host名は、dockerのネットワーク内であれば、docker-composeで定義したサービス名 `db` で参照できるのがポイント。

## 7. docker-compose up で各サービスを起動

```
$ docker-compose up
```

railsサーバーとmysqlサーバーを同時に起動してくれます。

## 8. dbをinitする （新規プロジェクトの場合のみ）

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

## 9. 完成

ブラウザで `http://localhost:3000` にアクセスして
welcomeページが表示されれば完成です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/52847/a836edf1-f8b2-daf8-aaf3-394277a7585d.png)


## 10. その後の開発で必要になりそうなこと

### サーバー停止

この起動したサーバーを停止するときは、 

```
$ docker-compose down
```
で行う。 `Ctrl + C` で終了すると、 
`tmp/pids/server.pid` が残り
次回起動するために手動で削除することになるので注意 :(

### Dockerfileやdocker-compose.ymlの変更を反映させたり、railsサーバーを再起動させる

```
$ docker-compose up --build
```

### bundle installなどコマンド実行

```
$ docker-compose run web bundle install
```

`docker-compose run {サービス名} {任意のコマンド}` で実行できる

### Macローカルからmysqlコンソールで接続

```
$ mysql -uroot -p -h0.0.0.0 -P3316
```

ホスト名が `localhost` では接続できないので注意 :( 

### コンテナに接続して中身を見たいとき


`docker ps` で実行中のコンテナIDを確認

```
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
f1d98f117c5d        qiitacopy_web       "bundle exec rails..."   4 seconds ago       Up 3 seconds        0.0.0.0:3000->3000/tcp   qiitacopy_web_1
b2ec856fc891        mysql               "docker-entrypoint..."   5 seconds ago       Up 4 seconds        0.0.0.0:3316->3306/tcp   qiitacopy_db_1
```

```
$ docker exec -it {コンテナID} /bin/bash
```