docker

【Rails】Docker環境下でのRails 5.2+Nginxで動かしてブラウザで確認

・Rails5.2(Puma)+NginxでのRailsアプリケーション動作方法
・Docker環境設定方法紹介

RailsアプリケーションをNginxで動かす方法の紹介となります。

EC2環境下で同じことやっているため基本的にはEC2環境でやったことと同じことをやるのですが、Dockerが挟まるということを変なふうに捉えてしまいDockerfileのところで詰まってしまいました。
備忘として作成した次第です。

EC2環境下での構築は下記を参照ください。

環境情報

各種バージョンは下記となります。

Ruby:2.6.3
Rails:5.2.1
Puma:3.11(Gemfile記載)
Nginx:1.21.1

Railsアプリケーションはrails newコマンドで作成されたプロジェクトを使っています。
作成したRailsアプリケーションは「/var/www/」直下に配置しています。

ディレクトリ構成

rails_hello
├─docker-compose.yml
├─.devcontainer
│   └─devcontainer.json
├─docker
│ ├─app_rails
│ │ └─Dockerfile
│ └─web_nginx
│    └─Dockerfile
├─nginx
│   default.conf
│   nginx.conf
└─workspace
  └─hello
    ├─config
    │ └─puma.rb
    └─tmp
       └─sockets
          └──puma.sock

ディレクトリ構成は上記とおりです。

workspaceディレクトリの中にRailsアプリケーションがあります。
今回Railsアプリケーションは必要なもののみ記載しています。

.devcontainerディレクトリはVSCode Remote Developmentプラグインに必要です。
詳しい使い方は今回省略しますが、別記事でKotlin環境構築を紹介していますので参照ください。

Rails設定

Dockerfile

FROM ruby:2.6.3

RUN apt-get update && apt-get install -y build-essential libpq-dev postgresql-client nodejs
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
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 && apt-get install -y yarn
# Node.jsをインストール
RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash -
RUN gem install rails -v 5.2.1

Puma.rb設定

threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count
# port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart
bind "unix://#{Rails.root}/tmp/sockets/puma.sock"

Dockerfileは単純なRubyとRailsとNode.jsのインストールです。

Puma.rbは3行目のPORT部分をコメントアウトしました。
また6行目を追加しました。puma.sockはプロジェクト作成時には無いですが「rails s」コマンドでPumaが立ち上がったときに作られます。

Nginx設定

Dockerfile

FROM nginx:latest
# インクルード用のディレクトリ内を削除
RUN rm -f /etc/nginx/conf.d/*
# ビルド完了後にNginxを起動
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

default.conf設定

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

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

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

  # ドキュメントルートの指定
  root /var/www/hello/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 @hello;
  keepalive_timeout 5;

  # リバースプロキシ関連の設定
  location @hello {
    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://web;
  }
}

nginx.conf設定

user  root;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    include /etc/nginx/conf.d/*.conf;
}

DockerfileはRailsのときと同じくNginxのインストールと実行です。
confファイルの削除は後述するconfファイルを毎回コンテナに配置したいので削除しています。

default.conf はPumaとの連携およびドメイン指定が必要です。
Railsアプリケーションのプロジェクトを指定する2箇所はパスに合わせて修正してください。
30行目のproxy_passは3行目のupstreamで指定した名前を設定してください。

nginx.conf は1行目にrootユーザーで参照するよう追加しました。
それ以外の箇所はデフォルト状態のままです。

docker-compose.yml設定

 version: "3"

services:
  app:
    build: ./docker/app_rails
    ports:
      - "3000:3000"
    environment:
      - "DATABASE_HOST=db"
      - "DATABASE_PORT=5432"
      - "DATABASE_USER=postgres"
      - "DATABASE_PASSWORD=mysecretpassword1234"
    depends_on:
      - db
      - web
    stdin_open: true
    tty: true
    volumes:
      - ./workspace:/var/www
  db:
    image: postgres:10.1
    ports:
      - "5432:5432"
    environment:
      - "POSTGRES_USER=postgres"
      - "POSTGRES_PASSWORD=mysecretpassword1234"
  web:
    build: ./docker/web_nginx
    ports:
      - 8080:80
    volumes:
      - ./workspace:/var/www
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf

docker-compose.yml は先程作成したDockerfile2つとデータベースを追加した3つのコンテナを定義しています。

注意すべき点としては、RailsとNginxのVolumesです。
NginxにてRailsのpuma.sockを参照するため、Nginxのコンテナでも見れるようにする必要があるため同じパスを設定しています。

これが無いと502 Bad Gateway が表示され、Nginxのログに「puma.sock failed (2: No such file or directory)」が出力されます。

Dockerコンテナ起動後設定

以上で各種環境の設定は完了です。
docker-compose.ymlファイルのある場所に対して「docker-compose up」コマンドを実行してコンテナを起動してください。

エラー無く、3つのコンテナが起動したらRailsアプリケーションに「bundle install」コマンドを行い、「rails s」コマンドでPumaが立ち上がります。
Nginxと連携されている場合は下記のような値が出力されます。

* Listening on unix:///var/www/hello/tmp/sockets/puma.sock

Pumaも立ち上がった後、default.confファイルの11行目(server_name)で設定したドメインをブラウザに打ち込みRails画面が表示されていることを確認してください。

Rails側に修正がある場合は、都度「rails s」コマンドの切断や接続を行えば反映されます。

最後に

以上でRailsアプリケーションをNginxで動作する方法の紹介となります。
1つ1つは難しく無いですが、やはり組み合わせとなると難易度が跳ね上がりますね。

学習用だとPuma単体で問題無いですがCD/CIを実現するとなるとNginxを使って、良い感じにしたいですね。

参考記事

https://serip39.hatenablog.com/entry/2020/12/23/235700