「Rails APIモードとReact Hooksを使ってToDoリストを作る」をdocker上に配置する

# 目的
これもやったことの備忘録が目的になります。
Know Howより、How to methodな内容にします

# 背景
バックエンドとフロントエンドを分けたアプリケーションをdockerにあと乗せする記事がなかったため。
せっかくやったのだから記事にしちゃおうって考えです。

# アウトライン
1. docker-compose.ymlを用意する
2. Dockerfile(Backend用)を用意する
3. entrypoint.shを用意する
4. Dockerfile(Frontend用)を用意する
5. rails側の調整
6. axiosmaterial-uiのインストール

やってみよう！
# docker-compose.yml
既存のrailsアプリ等に「後からdocker」を用意する場合でも、
アプリを作り始める時でも、やることはほとんど変わりません。

docker-compose.ymlはメインのディレクトリ上に配置します。

```yml:docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.6
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    volumes:
      - mysql-data:/var/lib/mysql 
    ports:
      - "4306:3306" #別件で3306は使っていたので4306を指定しました

  app:
    build: 
      context: .
      dockerfile: Dockerfile_back
    command: /bin/sh -c "rm -f /myapp/tmp/pids/server.pid && bundle exec rails s -p 3001 -b '0.0.0.0'"
    image: rails:dev
    volumes:
      - .:/myapp    #myappというところは任意で設定してください
      - ./app/vendor/bundle:/myapp/vendor/bundle 
    environment:
      TZ: Asia/Tokyo
      RAILS_ENV: development
    ports:
      - "3001:3001"
    depends_on: 
      - db

  front:
    build: 
      context: todo_front
      dockerfile: Dockerfile_front
    volumes:
      - ./todo_front:/todo_front
    command: /bin/sh -c "cd todo_front && yarn && yarn start"
    ports:
      - "3000:3000"

volumes:
  mysql-data:
  bundle: 
```

# Dockerfile(バックエンド用)を用意する
# entrypoint.shを用意する
Rubyのバージョンを既存のrailsアプリのRubyバージョンを合わせました。
それとmyappというのは任意になります。合わせてもOKです！
SQLが`mysql-client`と入力するとエラーになります。
いつしか、`mariadb-client`に統一されたようです。

`Dockerfile_back`と`entrypoint.sh`は`docker-compose.yml`と同じディレクトリ階層に配置しています。

```dockerfile:Dockerfile_back
FROM ruby:2.6.3

RUN apt-get update && \
    apt-get install -y mariadb-client nodejs vim

RUN mkdir /myapp

WORKDIR /myapp

ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock

RUN gem install bundler
RUN bundle install

ADD . /myapp

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3001

CMD ["rails", "server", "-b", "0.0.0.0"]
```

```sh:entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
```

# Dockerfile（frontend用)
`todo_front`ディレクトリ上に配置します。

```Dockerfile:Dockerfile_front
FROM node:14
```

# Rails側の調整
`database.yml'を調整してあげます。
socket通信になっているので、`host: db`に変えてあげます。

```yml:database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
- socket: /tmp/mysql.sock
+ host: db
```

# axiosmaterial-uiのインストール
コンテナをバックグラウンドで立ち上げます。
そして、axiosやmaterial-uiをインストールします。
ちなみに`exec`はすでにコンテナが立ち上がっている状態で使えます。
コンテナが立ち上がっていない時は`run`を使います。
終わったら、`db`を作って、マイグレートして、植えて終わりになります。

```console:console
$ docker-compose up -d #コンテナを立ち上げる
$ docker-compose exec front npm install axios
$ docker-compose exec front npm install @material-ui/core
$ docker-compose exec app bin/rails db:create
$ docker-compose exec app bin/rails db:migrate
$ docker-compose exec app bin/rails db:seed
```

`localhost:3000`にアクセスすると、前回と同じ画面が立ち上がるはずです。
終わり

# 終わりに
今回は、docker for Macの調子が悪く、何度もattachが発生しました。
再起動すると次のプロセスに行けました。
なんだろう、もう少しdockerの勉強した方がいいかなと思いました。
### Zennに投稿した記事
https://zenn.dev/nicoryo/articles/2020121402tech