Docker + React (Typescript) + Rails6 環境構築

# Summary
#### バックエンド Rails API & フロントエンド React & Docker の環境を実現したので手順をメモしておく 
1. Rails 初期設定ファイル作成
1. Rails & React 用のDocker関連ファイル作成
1. docker-compose.yml 作成
1. docker コマンド実行
1. database.yml の変更
1. docker-compose で起動

### ファイル構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/ee7689c4-24bd-3e7b-fd7d-81624402c5bc.png)
# 1. Rails 初期設定ファイル作成
```:Gemfile
source 'https://rubygems.org'
gem 'rails', '=>6'
```
```:Gemfile.lock
# 空
```
# 2. Rails & React 用のDocker関連ファイル作成
## Rails
```Dockerfile:Dockerfile
FROM ruby:2.7.2

# Rails6 からは以下のインストールが必要
# https://yarnpkg.com/lang/en/docs/install/#debian-stable
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
  echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
  apt-get update -qq && apt-get install -y nodejs postgresql-client vim && \
  apt-get install -y yarn && \
  apt-get install -y imagemagick && \
  apt-get install -y libvips-tools && \
  apt-get install -y locales

RUN curl -sL https://deb.nodesource.com/setup_7.x | bash - && \
    apt-get install nodejs

RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

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

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 "$@"
```
## React
```Dockerfile:Dockerfile
FROM node:14.16.0-alpine3.10
WORKDIR /usr/src/app
```

# 3. docker-compose.yml の作成
```yml:docker-compose.yml
version: "3.9"

services:
  db:
    image: postgres
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=password

  api:
    build:
      context: ./api/
      dockerfile: Dockerfile
    command: /bin/sh -c "rm -f /myapp/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - ./api:/myapp
      - ./api/vendor/bundle:/myapp/vendor/bundle
    environment:
      TZ: Asia/Tokyo
      RAILS_ENV: development
    ports:
      - 3000:3000
    depends_on:
      - db

  front:
    build:
      context: ./front/
      dockerfile: Dockerfile
    volumes:
      - ./front:/usr/src/app
    command: sh -c "cd frontend && yarn start"
    ports:
      - "8000:3000"

volumes:
  postgres-data:
    driver: local
```

# 4. docker コマンド実行
```
$ docker-compose run api rails new . --force --no-deps --database=postgresql --api
$ docker-compose build
# yarn でインストール、Typescript 対応
$ docker-compose run --rm front sh -c "yarn create react-app frontend --template typescript"
```
# 5. database.yml の変更
```yml:config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: 5

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

production:
  <<: *default
  database: myapp_production
  username: myapp
  password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>
```
# 6. docker-compose で起動
```
$ docker-compose up -d
$ docker-compose run api rails db:create
```
### 参考
- [DockerでRuby on Rails + Reactを別々にアプリ作成する環境構築手順](https://qiita.com/dl10yr/items/b76969da1c2c33595a4a)
- [PostgreSQL（Docker）にRails（Docker）が接続できなくなったから調べてみた。（could not translate host name "db" to address: Name or service not known）](https://qiita.com/at-946/items/2fb75cec5355fad4050d)