【保存版】Docker × React × Railsで環境構築していく方法

#はじめに
本記事へのアクセスありがとうございます。
投稿主はプログラミング初心者であり、この方法が「最適解」かは分かりません。
しかし、動作は検証済みであり同様な記事も確認できたので信憑性はあると思います。

記事通りにコピペしていくだけで環境構築できますので、説明がいらない人はコードだけをコピペして行ってください。



#想定読者
- Dockerインストール済み
- Docker初心者
- フロントエンド側とバックエンド側の開発環境を分けて構成したい
- 現在 ( 2020年12月 ）にある同様なQiita記事でエラーで詰まってしまっている

#最終ファイル構成
![qiita_docker1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691815/6ddc3941-c4e8-ba9d-6a97-2b09d6e5d0a2.png)


- apiの中にRailsファイルを格納されています。
- frontの中にReactファイルを格納されています。

#さっそくスタート
##初期ファイルを用意する
![qiita_docker2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691815/31a4d48b-1446-be76-d6cd-6a1045135ab9.png)
apiの中にはDockerfile , entrypoint.sh , Gemfile , Gemfile.lockの4つを作成する。
＊ **Gemfile.lockは何も記述しないファイルとする。**

###docker-compose.ymlの記述
docker-compose.ymlを記述していきます

```docker-compose.yml
version: '3'
services:
  db:
    image: postgres:12.3
    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'"
    image: rails:dev
    volumes:
      - ./api:/myapp
      - ./api/vendor/bundle:/myapp/vendor/bundle
      - ./api/vendor/node_modules:/myapp/vendor/node_modules
    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 react-sample && yarn start"
    ports:
      - "8000:3000"
volumes:
  postgres-data:
    driver: local
  bundle:
  node_modules:

```

###api / Dockerfileの記述
Dockerfileを記述していきます

```Dockerfile
FROM ruby:2.7
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarnpkg
RUN ln -s /usr/bin/yarnpkg /usr/bin/yarn
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
```

###api / entrypoint.shの記述
entrypoint.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 "$@"
```

###api / Gemfileの記述
Gemfileを記述していきます

```Gemfile
source 'https://rubygems.org'
gem 'rails', '~>6'
```

###front / Dockerfileの記述
Dockerfileを記述していきます

```Dockerfile
FROM node:10-alpine
RUN mkdir /myapp
WORKDIR /usr/src/app
```
＊ **node:10以上出ないと後々にcreate-react-app出来ないので注意してください**

##コマンドを実行する
まずは以下の3つのコマンドをターミナルで入力してください

```
$ docker-compose run api rails new . --force --no-deps --database=postgresql --api
$ docker-compose build
$ docker-compose run --rm front sh -c "npm install -g create-react-app && create-react-app react-sample"
```
api/config/database.ymlを下記のように書き換えてください

```api/config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  host: db
  username: postgres
  password: password
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
```
次に以下のコマンドをターミナルで入力してください

```
$ docker-compose up
```
以下のコマンドを現在まで使用しているターミナルとは別のターミナル（新規作成）で入力してください

```
$ docker-compose run api rake db:create
```
以上で環境構築が完了です。
#おわりに
この状況で...
localhost:3000にアクセスすると、Rails用のページにアクセスします。
localhost:8000にアクセスすると、React用のページにアクセスします。

お疲れ様でした。

少しでも役に立ったと思う方がいましたらLGTMをお願いします🙇‍♂️

#おまけ
Docker内で開発するときは以下のコマンドを利用します。

```
docker-compose run web bundle exec rails g コマンド
```