【Rails】【Docker】コピペでOK! DockerでRails開発環境を構築する方法

#【Rails】【Docker】コピペでOK! DockerでRails開発環境を構築する方法

## 目次
 * [構築イメージ](#構築イメージ)
 * [動作環境・前提条件](#動作環境前提条件)
 * [手順](#手順)
   * [STEP1. Dockerfileを作成する](#step1-dockerfileを作成する)
        * [STEP1.1 nginxのDockerfile](#step1-1-nginxのdockerfile)
        * [STEP1.2 nginxの設定ファイル](#step1-2-nginxの設定ファイル)
        * [STEP1.3 railsのDockerfile](#step1-3-railsのdockerfile)
   * [STEP2. pumaの設定](#step2-pumaの設定)
   * [STEP3. docker-composeの作成](#step3-docker-composeの作成)
   * [STEP4. データベースの設定](#step4-データベースの設定)
   * [STEP5. コンテナのビルド](#step5-コンテナのビルド)
   * [STEP6. データベースの作成](#step6-データベースの作成)
   * [STEP7. 確認](#step7-確認)
 
---------------------------------------
## 構築イメージ
今回は3つのコンテナを作成します.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526570/2bf26cce-2965-ce4e-e2f7-ccb65e544a80.png)


## 動作環境・前提条件

【動作環境】
`OS : macOS 10.14.6`
`Docker : 19.03.8`
`ruby : 2.6.5`
`rails : 5.2.4`

【前提条件】
Docker for Macをインストール済み

## STEP1. Dockerfileを作成する

まずはDockerフォルダと空ファイルを作成します.
ファイルの内容は後述します.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526570/28efe19c-48a7-9da9-500f-549356fd728d.png)

### STEP1-1. nginxのDockerfile

以下がnginxのdockerfileになります.
findpro-bangkokはアプリ名なので各自のアプリ名に変更してください.

```ruby:Dockerfile:nginx

FROM nginx:1.15.8

# インクルード用のディレクトリ内を削除
RUN rm -f /etc/nginx/conf.d/*

# Nginxの設定ファイルをコンテナにコピー
COPY /docker/nginx/nginx.conf /etc/nginx/conf.d/findpro-bangkok.conf

# 画像などのpublicファイルはnginxに配置
RUN mkdir -p /findpro-bangkok/public
COPY ./public /findpro-bangkok/public

# ビルド完了後にNginxを起動
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

```

### STEP1-2. nginxの設定ファイル

nginxの設定を記述するnginx.confを作成します.

```conf:nginx.conf
# プロキシ先の指定
# Nginxが受け取ったリクエストをバックエンドのpumaに送信
upstream puma {
  # ソケット通信したいのでpuma.sockを指定
  server unix:///findpro-bangkok/tmp/sockets/puma.sock;
}

server {
  listen 80 default;
  # ドメインもしくはIPを指定
  server_name localhost;

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  # ドキュメントルートの指定
  root /findpro-bangkok/public;

  client_max_body_size 100m;
  error_page 404             /404.html;
  error_page 505 502 503 504 /500.html;
  try_files  $uri/index.html $uri @puma;
  keepalive_timeout 5;

  # リバースプロキシ関連の設定
  location @puma {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://puma;
  }
}

```

### STEP1-3. railsのDockerfile

次にrailsのDockerfileを作成します.

```Dockerfile:Dockerfile
FROM ruby:2.6.5

RUN apt-get update -qq && \
  apt-get install -y apt-utils \
  build-essential \
  libpq-dev \
  nodejs \
  vim

#各自のアプリ名に変更する
ENV RAILS_ROOT /findpro-bangkok

RUN mkdir $RAILS_ROOT
WORKDIR $RAILS_ROOT

COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
RUN gem install bundler:2.1.4
RUN bundle install

#プロジェクトフォルダ内のすべてのファイルをRailsコンテナ内にコピーする
COPY . .

#ソケット通信のためのディレクトリを作成
RUN mkdir -p tmp/sockets

```


## STEP2. pumaの設定

以下のconfigフォルダ内のpumaの設定ファイルを編集します.
*pumaフォルダは本番用のフォルダのため今回は青のpuma.rbを編集します.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526570/d2e1a7f2-e494-bd72-5049-bf9cd7eb826f.png)

```ruby:puma.rb
threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 }.to_i
threads threads_count, threads_count
port        ENV.fetch('PORT') { 3000 }
environment ENV.fetch('RAILS_ENV') { 'development' }
plugin :tmp_restart

app_root = File.expand_path('..', __dir__)
bind "unix://#{app_root}/tmp/sockets/puma.sock"

stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true
```

## STEP3. docker-composeの作成

docker-composeは複数のコンテナのビルドをまとめて実行してくれる仕組みになります. 

docker-composeファイルをプロジェクトフォルダ直下に作成します.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526570/81e70ba4-9ff3-655a-d056-0a82268d7999.png)

```yml:docker-compose.yml
version: '3'
volumes:
  tmp_data:
  public_data:
services:
  nginx:
    build:
      context: ./
      dockerfile: ./docker/nginx/Dockerfile
    ports:
      - '80:80'
    volumes:
      - public_data:/findpro-bangkok/public
      - tmp_data:/findpro-bangkok/tmp/sockets
    depends_on:
      - app
    links:
      - app
  app:
    build:
      context: ./
      dockerfile: ./docker/rails/Dockerfile
    command: bundle exec puma
    volumes:
     #.:/findpro-bangkokでプロジェクトのカレントフォルダとコンテナのフォルダを同期しています.これによって変更した箇所を再度ビルドすることなく、コンテナに反映することができます.
      - .:/findpro-bangkok:cached
      #nginxとsocket通信するためにホストコンピュータ上にtmp_dataというファイルを作成し、nginxコンテナと共有しています.
      - tmp_data:/findpro-bangkok/tmp/sockets
      - public_data:/findpro-bangkok/public
    tty: true
    stdin_open: true
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: 'postgres'
```

## STEP4. データベースの設定

最後にdatabase.ymlでデータベースの設定をします.
今回はdevelopement環境のため、developmentまでの設定内容を記載します.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526570/dee149a0-8b35-7d72-cecd-7fd4217ac8ce.png)


*testやproductionの記述が下のほうにあるので、そちらは消さずにそのままにしておきます.

```yml
# PostgreSQL. Versions 9.1 and up are supported.
#
# Install the pg driver:
#   gem install pg
# On OS X with Homebrew:
#   gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On OS X with MacPorts:
#   gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
# On Windows:
#   gem install pg
#       Choose the win32 build.
#       Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem 'pg'
#
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  port: 5432
  username: postgres
  password: postgres
  pool: 5

  # For details on connection pooling, see Rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: findpro-bangkok_development

###以下省略

```


## STEP5. コンテナのビルド

それではいよいよ作成したコンテナを起動します.

まずはターミナルでプロジェクトフォルダに移動し、以下のコマンドを実行します.

```terminal
[JS-MAC findpro-bangkok]$ docker-compose build
```

ビルドが成功したあとに以下のコマンドを実行します.

```terminal
[JS-MAC findpro-bangkok]$ docker-compose up
```

## STEP6. データベースの作成

最後にデータベースを作成する必要があるので
もう一つ新規にターミナルを起動し、Railsコンテナに入ります。

```terminal
[@JS-MAC findpro-bangkok]$ docker ps #Railsコンテナ(findpro-bangkok_app)のIDを確認
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                NAMES
4549423f21ed        findpro-bangkok_nginx   "/bin/sh -c '/usr/sb…"   44 minutes ago      Up 3 seconds        0.0.0.0:80->80/tcp   findpro-bangkok_nginx_1
22ecc47308ae        findpro-bangkok_app     "bundle exec puma"       44 minutes ago      Up 5 seconds                             findpro-bangkok_app_1
755cb83a9bf4        postgres                "docker-entrypoint.s…"   44 minutes ago      Up 5 seconds        5432/tcp             findpro-bangkok_db_1
[@JS-MAC findpro-bangkok]$ docker exec -it 22e /bin/sh #Railsコンテナにログインする.22eはappコンテナのIDの頭文字です.
# rails db:create #データベースを作成する.
Database 'findpro-bangkok_development' already exists
Database 'findpro-bangkok_test' already exists
# rails db:migrate #マイグレーションを実行する.
```

## STEP7. 確認

最後にchromeでlocalhostと打ち確認します.