こんにちは。Enjoy IT Life管理人の仁科(@nishina555)です。
Railsアプリケーションを開発する際、開発環境であればrails s
を実行するだけで簡単にアプリケーションを立ち上げられます。
しかし、実際にサービスをリリースする際は本番環境の構築が必要です。
今回はRailsアプリケーションの本番環境の構築手順について紹介します。
検証サーバーはConoHa VPS、OSはCentOS8を利用します。
目次
今回作成する本番環境の詳細について
各種バージョンは下記の通りです。
$ cat /etc/redhat-release
CentOS Linux release 8.1.1911 (Core)
$ node -v
v12.18.0
$ ruby -v
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
$ rails -v
Rails 6.0.3.1
$ mysqld --version
/usr/libexec/mysqld Ver 8.0.17 for Linux on x86_64 (Source distribution)
$ mysql --version
mysql Ver 8.0.17 for Linux on x86_64 (Source distribution)
$ nginx -v
nginx version: nginx/1.14.1
- VPSのCentOSイメージ上に、『Rails6 + MySQL8』のアプリケーションを配置する
- Pumaを利用してnginx(Webサーバー)を連携させる
- 作業ユーザーは事前に作成した『webuser』というroot権限を持つユーザー
- ソースコードは『rails new』ではなく『git』を利用し、『/srv』ディレクトリ配下に配置
- アプリケーション名は『rails-app』
Railsアプリケーションの環境構築
まずはCentOS上にRailsアプリケーションが起動する環境を構築します。
この項目で紹介する『Rails6 + MySQL8』の開発環境の構築手順については『Rails6 + MySQL8の開発環境をCentOS8に構築する手順』で紹介していますので、コマンドの意味の詳細などについてはそちらの記事を参考にしてください。
Rubyのインストール
rubyのバージョン管理ができるrbenvを利用してRubyのインストールを行います。1 2 3 4
### rbenvのインストール
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ ~/.rbenv/bin/rbenv init
→ 手順が出力されるのでそれに従う
### 推奨ライブラリのインストール
$ sudo yum install -y gcc.x86_64 bzip2 openssl-devel libffi-devel readline-devel zlib-devel gdbm-devel ncurses-devel make
### 推奨ライブラリlibyaml-develはPowerTools経由でインストール
$ sudo dnf --enablerepo=PowerTools install -y libyaml-devel
### ruby-buildのインストール
$ mkdir -p "$(rbenv root)"/plugins
$ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
### セットアップが正しく完了したかチェックする
$ curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash
Checking for `rbenv' in PATH: /home/webuser/.rbenv/bin/rbenv
Checking for rbenv shims in PATH: OK
Checking `rbenv install' support: /home/webuser/.rbenv/plugins/ruby-build/bin/rbenv-install (ruby-build 20200520-2-gf00582b)
Counting installed Ruby versions: none
There aren't any Ruby versions installed under `/home/webuser/.rbenv/versions'.
You can install Ruby versions like so: rbenv install 2.2.4
Checking RubyGems settings: OK
Auditing installed plugins: OK
### rubyのインストール
$ rbenv install -v 2.7.1
$ rbenv global 2.7.1
$ rbenv versions
→ バージョンが表示されればOK
* 2.7.1 (set by /home/webuser/.rbenv/version)
Node.jsのインストール
Rails6ではデフォルトでWebpacekrを利用します。Webpackerを利用するにはNode.jsが必要なのでインストールをします。
nodeはnodenvを利用してインストールします。手順はrubyをrbenvを利用してインストールしたときのそれとほとんど同じです。5 6 7
### nodenvのインストール
$ git clone https://github.com/nodenv/nodenv.git ~/.nodenv
$ echo 'export PATH="$HOME/.nodenv/bin:$PATH"' >> ~/.bash_profile
$ ~/.nodenv/bin/nodenv init
→ 手順が出力されるのでそれに従う
### 推奨ライブラリのインストール
$ sudo yum install -y python36.x86_64 gcc-c++ make
### node-buildのインストール
$ mkdir -p "$(nodenv root)"/plugins
$ git clone https://github.com/nodenv/node-build.git "$(nodenv root)"/plugins/node-build
### セットアップが正しく完了したかチェックする
$ curl -fsSL https://github.com/nodenv/nodenv-installer/raw/master/bin/nodenv-doctor | bash
Checking for `nodenv' in PATH: /home/webuser/.nodenv/bin/nodenv
Checking for nodenv shims in PATH: OK
Checking `nodenv install' support: /home/webuser/.nodenv/plugins/node-build/bin/nodenv-install (node-build 4.9.0)
Counting installed Node versions: none
There aren't any Node versions installed under `/home/webuser/.nodenv/versions'.
You can install Node versions like so: nodenv install 2.2.4
Auditing installed plugins: OK
### nodeのインストール
$ nodenv install -v 12.18.0
$ nodenv global 12.18.0
$ nodenv versions
→ バージョンが表示されればOK
* 12.18.0 (set by /home/webuser/.nodenv/version)
Yarnのインストール
Webpacekrで必要になるYarnのインストールを行います。8
$ curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
$ sudo yum install -y yarn
$ yarn -v
1.22.4
MySQLの準備
MySQLのインストールを行います。
### mysql2 gemをインストールするのに必要なのでインストールしておく
$ sudo yum install -y mysql-devel
### MySQLのインストール
$ sudo yum install -y mysql-server
$ mysqld --version
→ バージョンが表示されればOK
/usr/libexec/mysqld Ver 8.0.17 for Linux on x86_64 (Source distribution)
インストールが完了したらMySQLを起動します。
### 起動
$ sudo systemctl start mysqld.service
### ステータス確認
$ sudo systemctl status mysqld
Active: active (running)
### 常時起動にする
$ sudo systemctl enable mysqld.service
Created symlink /etc/systemd/system/multi-user.target.wants/mysqld.service → /usr/lib/systemd/system/mysqld.service.
Railsアプリケーションの配置
Railsアプリケーションの配置と起動の準備を行います。
### gitのインストール
$ sudo yum install -y git
### アプリケーションディレクトリの作成
$ cd /srv
$ sudo mkdir rails-app
$ sudo chown webuser:webuser rails-app
### rails-appディレクトリでgit clone
$ cd rails-app
$ git clone git@github.com:xxxx/rails-app.git .
### gemのインストール
$ bundle install
### Webpackerのインストール
$ bin/rails webpacker:install
データベース接続ユーザーの作成と権限付与を行います。
今回はwebuser
というユーザーがwebpass
というパスワードでデータベースに接続できるようにします。
$ mysql -u root -p
### ユーザー作成
mysql> create user webuser@'localhost' identified by 'webpass';
### webuserに権限付与
mysql> grant all on *.* to webuser@'localhost';
Webサーバー(nginx)の準備
多くのリクエストをさばけるようにするため、WebサーバーとRailsアプリケーションを連携させます。
今回はPumaを利用した連携方法について紹介します。Webサーバーはnginxを利用しています。
この項目で紹介するWebサーバーとRailsアプリケーションの連携手順は『nginxとPumaを連携し、nginx + Puma + Rails6の開発環境を構築する手順』で紹介していますので、コマンドの意味の詳細などについてはそちらの記事を参考にしてください。
nginxの準備
nginxのインストールと起動を行います。
### インストール
$ sudo yum install -y nginx
### nginxの起動
$ sudo systemctl start nginx
### 自動起動設定
$ sudo systemctl enable nginx
Pumaの設定ファイルの編集
PumaとWebサーバーが連携できるようにPumaの設定を編集します。
Pumaではデフォルトの設定ファイルであるconfig/puma.rb
のほか、実行環境に応じたconfig/puma/[実行環境].rb
という設定ファイルを用意できます。
本番環境用のPumaの設定はconfig/puma/production.rb
に記述するとよいでしょう。
$ vim /srv/rails-app/config/puma/production.rb
config/puma/production.rb
# 以下の部分をコメントアウト
# port ENV.fetch("PORT") { 3000 }
# socketの設定
bind "unix://#{Rails.root}/tmp/sockets/puma.sock"
# デーモン化(バックグラウンドでRailsを起動)
daemonize
nginxの設定ファイルの編集
Pumaと連携できるようにnginxの設定ファイルを編集します。
$ sudo vim /etc/nginx/conf.d/rails-app.conf
rails-app.conf
upstream rails-app {
# UNIXドメインソケット通信の設定
server unix:///srv/rails-app/tmp/sockets/puma.sock fail_timeout=0;
}
server {
# 80番ポート(HTTP)を許可
listen 80;
# ホスト名
server_name xxxxxx;
# 静的ファイル(画像など)のパスをドキュメントルートに設定
root /srv/rails-app/public;
location / {
# ドキュメントルート配下を以下の順で検索
# URIのパスに対するファイル(静的コンテンツ)が存在すれば、そのファイル返す。
# 存在しなければ、動的コンテンツとして@rails-appに内部リダイレクト。
try_files $uri @rails-app;
}
# nginxのリバースプロキシ設定
# 上記の@rails-appが呼び出された場合のみ以下の設定が読み込まれる
location @rails-app {
# サーバの指示通りにリダイレクト
proxy_redirect off;
# proxy_set_headerを利用することでサーバーに情報を転送できる
proxy_set_header Host $http_host; # ホスト名
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 送信元の経路情報
proxy_set_header X-Real-IP $remote_addr; #送信元のIPアドレス
# upstreamの名前を記述
proxy_pass http://rails-app;
}
}
秘匿情報(credentials)の設定
本番環境でRailsアプリケーションを起動させるにはsecret_key_base
を秘匿情報に登録する必要があります。
secret_key_baseとは、署名入りCookieをはじめとした暗号化された情報の検証を行う際に利用される秘密鍵です。
secret_key_baseを利用することで情報の改ざんを防ぐことができます。
秘匿情報の管理方法はRailsのバージョンによって異なります。
Rails5.2からはsecrets.yml
が廃止され、秘匿情報は暗号化されたファイルcredentials.yml.enc
と、それを復号するmaster.key
のペアで管理するようになりました。
rails new
を実行するとcredentials.yml.enc
とmaster.key
のペアが作成されます。
しかしmaster.key
は.gitignore
されているため『git pull』でソースコードを配置する』という、本番環境でよく利用されるオペレーションではマスターキーを配置できません。
秘匿情報を本番環境で扱えるようにする方法は3つあります。
- master.keyを開発環境からコピーしてくる方法
- 環境変数にマスターキーをセットする方法
- 本番環境用のcredentialsファイルとマスターキーのペアを作成する方法
今回は『本番環境用のcredentialsファイルとマスターキーのペアを作成する方法』を利用して秘匿情報を本番環境で管理します。
Rails6ではmulti environment credentials機能が追加され、環境ごとにcredentialsファイルとキーのペアを用意できるようになっています。9
本番環境用のcredentialsファイルとキーのペアであるproduction.yml.enc
とproduction.key
を作成し、secret_key_base
をproduction.yml.enc
に登録します。
デフォルトで用意されているcredentials.yml.enc
にはsecret_key_base
があらかじめ登録されていますが、環境別のcredentialsファイルにはsecret_key_baseが登録されていません。
ですので、rails secret
を実行してsecret_key_base
用の擬似乱数を事前に用意しておくとよいです。
### セッションシークレット用に擬似乱数の生成。シークレットキーを簡単に生成するコマンド
$ bin/rails secret
→ 出力される乱数をコピー
### config/credentials.yml.encの編集
$ EDITOR="vim" bin/rails credentials:edit --environment production
or
$ export EDITOR="vim"
$ bin/rails credentials:edit
→ このタイミングでconfig/credentials/production.keyとconfig/credentials/production.yml.encが作成される
config/credentials/production.yml.enc
secret_key_base: "コピーした乱数をペースト"
credentialsファイルに保存した値はRails.application.credentials.xxx
で確認できます。
$ bin/rails c -e production
> Rails.application.credentials.secret_key_base
→ credentialsファイルに登録したsecret_key_baseのvalueが出力されればOK
なお、今回紹介を省略しましたが『環境変数にマスターキーをセットする方法』の場合、master.key
であればRAILS_MEASTER_KEY
、production.key
であればRAILS_PRODUCTION_KEY
という環境変数名で登録すればOKです。
エラー対応: No $EDITOR to open file in. Assign one like this
credentialsファイルを開く際にbin/rails credentials:edit
と実行するとNo $EDITOR to open file in. Assign one like this:
というエラーが発生します。
これは、環境変数『EDITOR』がセットされていないのが原因です。
ですので、credentialsファイルを開く際はエディターの指定も必ず行うようにしてください。
シェルの設定ファイルでEDITOR
をセットすれば、以下のようにbin/rails credentials:edit
でファイルが開けます。
### .bash_profileに環境変数 EDITOR を設定する
$ echo 'export EDITOR="vim"' >> ~/.bash_profile
$ source ~/.bash_profile
### EDITORをコマンドで指定しなくても編集できるようになる
$ bin/rails credentials:edit
環境変数の設定
環境変数の管理方法は2つあります。
- シェルの設定ファイルに記述する方法
- dotenv-railsというgemを利用する方法
今回は『シェルの設定ファイルに記述する方法』で環境変数を管理します。
例としてconfig/database.yml
に記載されている、本番環境用のパスワードENV['RAILS_APP_DATABASE_PASSWORD']
の値をセットします。
今回の環境ではbash
を利用しているため.bash_profile
に環境変数を保存します。
設定ファイルをリロード後、rails console
で環境変数の値が確認できればOKです。
$ echo 'export RAILS_APP_DATABASE_PASSWORD="xxx"' >> ~/.bash_profile
$ source ~/.bash_profile
$ bin/rails c -e production
> ENV['RAILS_APP_DATABASE_PASSWORD']
→ 設定したパスワードが表示されればOK
アセットのコンパイル
本番環境ではアセットを事前にコンパイルしておく必要があります。
Rails6からはWebpackerが標準でGemfileに追加されるようになり、JavaScriptのコンパイルはWebpackerが、CSSおよび画像ファイルのコンパイルはSprockets4が行っています。
アセットのコンパイルは以下のコマンドで実施します。
$ bin/rails assets:precompile
$ ls public/assets/
→ ファイルがあればOK
$ ls public/packs/
→ ファイルがあればOK
コマンドを実行することで、app/assets
配下とapp/packs
配下のアセットファイルがコンパイルされてpublic/
配下に配置されます。
public/
配下にassets
とpacks
ディレクトリが配置され、ファイルが生成されていることが確認できればOKです。
データベースの用意
本番環境用のデータベースの作成とマイグレーションを実行します。
$ bin/rails db:create RAILS_ENV=production
$ bin/rails db:migrate RAILS_ENV=production
本番環境での起動確認
本番環境でRailsアプリケーションを起動する準備が整ったので、確認を行っていきます。
### nginxを再起動
$ sudo systemctl restart nginx
### Railsを起動
$ bin/rails s -e production
→ Pumaでデーモン化の設定を行っている場合、バックグラウンドでRailsが起動します。
http://[パブリックIP]/*
で画面が表示できればOKです。
たとえば、Eventというモデルをscaffoldで作成したサンプルアプリケーションの場合、http://[パブリックIP]/events
で以下のような画面が表示されます。

もし画面にアクセスできない場合、サーバーのファイアウォールの設定が悪さをしている可能性があります。
Webサーバーがlistenしている80番ポートで接続できるようにするため、必要に応じてファイアウォールの設定を変更しておきましょう。
### 80番ポートの開放
$ sudo firewall-cmd --add-port=80/tcp --zone=public --permanent
### 設定を反映
$ sudo firewall-cmd --reload
### 設定確認
$ sudo firewall-cmd --list-all
まとめ
以上でnginx + Puma + Rails6 + MySQLの本番環境をCentOS8に構築する手順の紹介を終わります。
- Railsアプリケーションの環境構築
- Webサーバー(nginx)の準備
- 秘匿情報(credentials)の設定
- 環境変数の設定
- アセットのコンパイル
- データベースの用意
なお、今回検証サーバーを用意するために利用したConoHa VPSは、1ヶ月に満たない利用の場合は時間単位で料金が請求されるので、数十円くらいでサーバーの勉強や検証環境が用意できるオススメのVPSです!
この記事がいいなと思いましたらツイッター(@nishina555)のフォローもよろしくお願いします!
Rubyのオススメ参考書
- rbenv『README#Basic GitHub Checkout』 ↩
- ruby-build『README#Installation』 ↩
- ruby-build『Wiki#Suggested build environment』 ↩
- pkgs.org『libyaml-devel-0.1.7-5.el8.x86_64.rpm』 ↩
- nodenv『README#Basic GitHub Checkout』 ↩
- node-build『README#Installation』 ↩
- node『BUILDING.md#Building Node.js on supported platforms』 ↩
- Yarn『Installation』 ↩
- rails『Add support for multi environment credentials』 ↩