docker-syncを使用したrails + mysqlの環境構築

docker-sync使って環境構築するのってどうやるんだろって思ってメモ感覚で一回作ってみました。

###環境
Mac
Ruby 2.6.1
Rails 5.2.3
MySQL 5.7

###dockerインストール
こちらでインストール
https://hub.docker.com/editions/community/docker-ce-desktop-mac

###作業ディレクトリを作成

```ruby
$ mkdir hoge
$ cd hoge
```

pwdしたらhogeにいたらそこで作業します

コンテナ用のディレクトリを作成して
そこでアプリケーション用のDockerfileを作成


```ruby:
$ mkdir containers/web
$ touch Dockerfile
```

```ruby:Dockerfile

FROM gendosu/ruby-node:ruby-2.6.1-node-10.15.1
ENV LANG C.UTF-8
ENV APP_ROOT=/hoge
ENV NODE_OPTIONS=--max-old-space-size=8192

RUN apt-get update -qq \
    &&  apt-get install -y --no-install-recommends \
        build-essential nodejs vim sudo \
        mysql-client \
    && rm -rf /var/lib/apt/lists/*

RUN mkdir /var/lib/mysql && touch /var/lib/mysql/mysql.sock
ADD ./containers/mysql/my.cnf /etc/

RUN mkdir $APP_ROOT
WORKDIR $APP_ROOT

RUN gem install bundler -v "1.17.2"

COPY Gemfile /$APP_ROOT/Gemfile
COPY Gemfile.lock /$APP_ROOT/Gemfile.lock

RUN bundle install

EXPOSE 3000
EXPOSE 22

# vue
RUN yarn install
```
今回はvueも入れたいので`gendosu/ruby-node:ruby-2.6.1-node-10.15.1`のimageを導入



ついでにMysql用のDockerfileとmy.cnfも作成


```ruby:
$ mkdir containers/mysql
$ touch Dockerfile
$ touch my.cnf
```

``` ruby:Dockerfile
FROM mysql:5.7

ADD ./containers/mysql/my.cnf /etc/mysql/my.cnf

RUN chmod 644 /etc/mysql/my.cnf

EXPOSE 3306
```

```ruby:my.cnf
[mysqld]

# #################
# character
# #################
character-set-server=utf8mb4
explicit_defaults_for_timestamp = true

# #################
# innodb
# #################

innodb_buffer_pool_size=6G
innodb_log_buffer_size=64M
innodb_log_file_size=1G
innodb_file_per_table=1

# #################
# query cache
# #################

query_cache_limit=16M
query_cache_size=512M
query_cache_type=1

# #################
# slow query log
# #################

slow_query_log=ON
long_query_time=3

# #################
# etc
# #################

join_buffer_size=256K
max_allowed_packet=8M
read_buffer_size=1M
read_rnd_buffer_size=2M
sort_buffer_size=4M
max_heap_table_size=16M
tmp_table_size=16M
thread_cache_size=100
wait_timeout=30

[client]
default-character-set=utf8mb4
```


###次にGemfileを作成

```
$ touch Gemfile
```

``` ruby:Gemfile
source 'https://rubygems.org'

# framework
gem('rails', '~> 5.2.3')
```

###Gemfile.lockも作成

```ruby:Gemfile.lock

$ touch Gemfile.lock
# 中身は書かなくてオッケー
```

###docker-composeを作成

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

```ruby:docker-compose.yml
version: '3'

services:
  db:
    build:
      context: .
      dockerfile: ./containers/mysql/Dockerfile
    environment:
      - MYSQL_ROOT_PASSWORD=password
    ports:
      - '13306:3306'
    volumes:
      - ./containers_data/mysql:/var/lib/mysql

  web:
    build:
      context: .
      dockerfile: ./containers/web_app/Dockerfile
    command: bundle exec rails s -p 3000
    environment:
      MYSQL_ROOT_PASSWORD: 'password'
      AUTODOC: 0
      RAILS_ENV: 'development'
    depends_on:
      - db
    ports:
      - "3000:3000"
    links:
    - db
    tty: true
    stdin_open: true

```

###新規Railsプロジェクトの作成
現在のディレクトリにプロジェクトを作成します。データベースをmysqlに指定してRailsプロジェクト作成時にbundle installを行わないようしてここではrailsのデフォルトのminitestというテストを使わない時に付けました

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

###database.ymlの変更

```
$ cd hoge/config
$ vim database.yml
```

``` ruby:database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password 
  host: db ←compose.ymlに書いたmysqlコンテナのservice名
```


##次にdocker-sync
rsyncやunisonでホスト側をコンテナ側に転送する仕組みらしいです

###docker-syncのインストール

**ローカルでインストール**

```
$ gem install docker-sync 
$ brew install fswatch 
$ brew install unison
```

###docker-sync.ymlの作成
docker-syncの設定はdocker-sync.ymlに書きます

hoge配下に作成します（docker-compose.ymlと同じ階層）


```
$ vi docker-sync.yml
```


``` ruby:docker-sync.yml
docker-sync.yml
version: '2'

syncs:
  sync-volume:
    src: '~/hoge/'
    #自分の作業ディレクトリパスを指定

```

###docker-syncを起動

プロジェクトディレクトリ内で `$ docker-sync start`
sync完了したら次にコンテナをbuild

`$ docker-compose build`
**（すっ飛ばしたい方はdocker-compose up --buildでまとめてビルドも起動もしてください）**

DBを作成します 
`$ docker-compose run web bundle exec rails db:create`

ビルドとDB作成終了後 `$ docker-compose up` で起動

起動しているdockerのコンテナ一覧 `$ docker ps`

コンテナへ入る　 `$ docker exec -it [コンテナID] bash`  作業はコンテナ内で行う。

マイグレーション `$ bundle exec rails db:migrate`

これで環境構築完了

### コマンド一覧

全コンテナ停止　` $ docker stop $(docker ps -q)　 `
全コンテナ削除　 `$ docker rm $(docker ps -q -a) `
全イメージ削除　 `$ docker rmi $(docker images -q) `
コンテナへ入る　 `$ docker exec -it [コンテナID] bash` 
マイグレーション `$ bundle exec rails db:migrate`

**rails系**
ロールバック `$ bundle exec rails db:rollback `
確認 `$ bundle exec rails db:migrate:status `
リセット `$ bundle exec rails db:migrate:reset `
モデル作成 `$ bundle exec rails g model [モデル名] `
コントローラーの階層作成 `$ bundle exec rails g controller hoge::hoges`

**データベースのmigrateの切り替え** 
ローカル用 `$ bundle exec rails db:migrate RAILS_ENV=local `
開発環境用 `$ bundle exec rails db:migrate RAILS_ENV=development `
本番環境用 `$ bundle exec rails db:migrate RAILS_ENV=production`

###まとめ
正直この量ならsyncしなくても大丈夫かもしれないです....でもやってみたかった！！！
もし間違えてたり、こっちのがいいよーってのがございましたら教えていただけると幸いです！！！