【備忘録】【環境構築】Docker + Ruby on Rails + ReactでSPA化

RailsとReactを使ってSPA化したWebアプリをDocker環境で作ろうとして、結構苦労したため、自分用のメモとして残します。

# 各種ファイルの用意

プロジェクト用のフォルダを用意して、Rails側のapiフォルダとReact側のfrontフォルダに分ける。
プロジェクト用フォルダの直下に、docker-compose.ymlを置く。

```
$ mkdir -p ~/project/rails-react-app
$ cd ~/project/rails-react-app
$ mkdir ~/project/rails-react-app/api
$ touch ~/project/rails-react-app/api/Dockerfile
$ touch ~/project/rails-react-app/api/entrypoint.sh
$ touch ~/project/rails-react-app/api/Gemfile
$ touch ~/project/rails-react-app/api/Gemfile.lock
$ mkdir ~/project/rails-react-app/front
$ touch ~/project/rails-react-app/front/Dockerfile
```

docker-composeファイル作成

```
$ cd ~/project/rails-react-app
$ vim docker-compose.yml
```

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

services:
  db:
    image: postgres
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: 'postgres'
  api:
    build: 
      context: ./api/
      dockerfile: Dockerfile
    command: /bin/sh -c "rm -f /rails-react-app/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    image: rails:dev
    volumes:
      - ./api:/rails-react-app
      - ./api/vendor/bundle:/rails-react-app/vendor/bundle
    environment:
      TZ: Asia/Tokyo
      RAILS_ENV: development
    ports:
      - 3001:3000
    depends_on:
      - db
  front:
    build: 
      context: ./front/
      dockerfile: Dockerfile
    volumes:
      - ./front:/usr/src/app
    command: sh -c "cd rails-react-app && yarn start"
    ports:
      - "8000:3000"
volumes:
  postgres-data:
    driver: local
```

RailsとReactでDockerfileを別々に用意したので、buildの部分でDockerfileの場所を指定したのがポイント。

```ruby:docker-compose.yml
api:
    build: 
      context: ./api/
      dockerfile: Dockerfile

  front:
    build: 
      context: ./front/
      dockerfile: Dockerfile
```

# Rails用のファイルの用意

```ruby:~/project/rails-react-app/api/Dockerfile
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /rails-react-app
WORKDIR /rails-react-app
COPY Gemfile /rails-react-app/Gemfile
COPY Gemfile.lock /rails-react-app/Gemfile.lock
RUN bundle install
COPY . /rails-react-app

# 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"]
```

### Gemfile

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

### Gemfile.lock

これは空ファイルを用意。

### entrypoint.sh

```
#!/bin/bash
set -e

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

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


# React用のファイルの用意

```ruby:~/project/rails-react-app/front/Dockerfile
FROM node:12.22-alpine3.11  
WORKDIR /usr/src/app
```

# コマンドの実行

React: create-react-appを用いて環境構築（参考記事: https://blog.web.nifty.com/engineer/2714 ）

```
$ 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 rails-react-app"
```

### api/config/database.ymlの書き換え

```ruby:api/config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: postgres
  pool: 5

development:
  <<: *default
  database: rails-react-app_development

test:
  <<: *default
  database: rails-react-app_test
```

```
$ docker-compose up
$ docker-compose run api rake db:create
$ docker-compose run api rake db:migrate
```

これで環境構築完了！

Rails: localhost:3001
React: localhost:8000



▼参考にさせていただいた記事

https://qiita.com/dl10yr/items/b76969da1c2c33595a4a#react-localhost8000

https://qiita.com/mkato7914/items/4938969fe1a90d23c7fb