Ubuntu 20.04上でRuby on Railsをnginxで動かす
はじめに_
Ubuntu 20.04 on WSL2上でRuby on Railsをnginxで動かす。実現したい状況は以下のとおり。
- http://locahost:30080 にWindows上のWebブラウザからアクセスするとRailsアプリにアクセスできる
- Webサーバnginxは30080ポートにアクセスがあったら、unicornを通して、Railsアプリを呼び出す
- nginxとunicornはUnixソケットを通じて連携する
参考_
- Webサーバー「Unicorn」の基本情報と実装方法
- WEB/APサーバ構成に応じたNginx設定
- nginxでsites-availableとsites-enabledを用いたバーチャルホストの設定
nginxのインストールと設定_
% sudo apt install -y nginx
デフォルトの設定のままだと以下のようなメッセージがエラーログに表示される。
2021/10/05 15:25:49 [alert] 1532#1532: *2630 768 worker_connections are not enough while connecting to upstream, client: 127.0.0.1, server: , request: "GET / HTTP/1.0", upstream: "http://127.0.0.1:30080/", host: "localhost:30080"
worker_connectionsとworker_rlimit_nofileの値は何がいいのか?に従い、worker_connectionsとworker_rlimit_nofileの値の設定を変える。
Ubuntu 20.04(Debian GNU/Linuxも)は /etc/nginx/nginx.conf で設定されている。まず、設定ファイルのコピーをする。
% cd /etc/nginx % sudo cp -p nginx.conf nginx.conf.org
お好きなエディタで編集する(編集の際はroot権限が必要)。nginx.confのworker_connectionsとworker_rlimit_nofileの値を編集する。
user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; ## 以下を追記する worker_rlimit_nofile 83000; events { ### 以下の値を変更する #worker_connections 768; worker_connections 4096; # multi_accept on; } ~以下略~
設定が正しいかどうか確かめる。
% sudo nginx -t [sudo] gotoh のパスワード: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
nginxを再起動する。
% sudo service nginx restart
unicornのインストールと設定_
RailsアプリとWebサーバをつなぐミドルウェアとしてunicornを用いる。unicornの役割については以下のページが丁寧に説明してくれている。
動作確認用のRailsアプリの準備_
動作確認用のRailsアプリを作成する。(参考:rbenvを用いたRuby on Rails環境の構築 on Ubuntu 20.04)
% cd % mkdir -p ~/Sandboox/RailsTest % cd ~/Sandboox/RailsTest (Windows Subsystem for Linux上のUbuntuの場合) % rails new demo --skip-bundle -skip-spring --skip-listen % cd demo % bundle install % rails webpacker:install % rails generate scaffold person name:string age:integer % rails db:migrate
Railsアプリの動作確認をする。
% rails server => Booting Puma => Rails 6.1.4.1 application starting in development => Run `bin/rails server --help` for more startup options Puma starting in single mode... * Puma version: 5.4.0 (ruby 3.0.2-p107) ("Super Flight") * Min threads: 5 * Max threads: 5 * Environment: development * PID: 20564 * Listening on http://127.0.0.1:3000 * Listening on http://[::1]:3000 Use Ctrl-C to stop
Webブラウザで、http://localhost:3000/people にアクセスし、アプリが動いていることを確認する。確認したらアプリを Ctrl-cで停止する。
unicornのインストールと設定_
Gemfileに以下を追記する。
gem 'unicorn'
インストールする。
% bundle install
Webサーバー「Unicorn」の基本情報と実装方法に従い config/unicorn.rb を記述する。また、各種ファイルを設置するディレクトリを作成する。
% touch config/unicorn.rb % mkdir -p tmp/pids % mkdir -p tmp/sockets
config/unicorn.rb の中身は以下のようにする。
# Refer to https://www.autovice.jp/articles/146 # Railsアプリのルート rails_root = File.expand_path('../../', __FILE__) # Gemfileの場所 ENV['BUNDLE_GEMFILE'] = rails_root + "/Gemfile" # Unicornの設定 worker_processes 2 timeout 15 working_directory rails_root pid File.expand_path 'tmp/pids/unicorn.pid', rails_root listen File.expand_path 'tmp/sockets/.unicorn.sock', rails_root stdout_path File.expand_path 'log/unicorn.log', rails_root stderr_path File.expand_path 'log/unicorn.log', rails_root preload_app true # フォークが行われる前の処理 before_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! old_pid = "#{server.config[:pid]}.oldbin" if old_pid != server.pid begin Process.kill "QUIT", File.read(old_pid).to_i rescue Errno::ENOENT, Errno::ESRCH end end end # フォークが行われた後の処理 after_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end # フォークが行われる前の処理 before_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! end # フォークが行われた後の処理 after_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end # フォークが行われる前の処理 before_fork do |server, worker| old_pid = "#{server.config[:pid]}.oldbin" if old_pid != server.pid begin Process.kill "QUIT", File.read(old_pid).to_i rescue Errno::ENOENT, Errno::ESRCH end end end
続いて、unicornをNginx環境下で動かす時の設定方法に基づいて、unicornを起動するタスクファイルを設定する。
% rails g task unicorn }} lib/tasks/unicorn.rakeを以下のように編集する。なお、上述の config/unicorn.rb のPIDファイルの設置場所に合わせて、一部変更している。 {{{ # Refer to https://y-hilite.com/2857/ # Modified above setting according to current config/unicorn.rb namespace :unicorn do # Tasks desc "Start unicorn" task(:start) { config = Rails.root.join('config', 'unicorn.rb') sh "unicorn -c #{config} -E development -D" } desc "Stop unicorn" task(:stop) { unicorn_signal :QUIT } desc "Restart unicorn with USR2" task(:restart) { unicorn_signal :USR2 } desc "Increment number of worker processes" task(:increment) { unicorn_signal :TTIN } desc "Decrement number of worker processes" task(:decrement) { unicorn_signal :TTOU } desc "Unicorn pstree (depends on pstree command)" task(:pstree) do sh "pstree '#{unicorn_pid}'" end # Helpers def unicorn_signal signal Process.kill signal, unicorn_pid end def unicorn_pid begin unicorn_pid = Rails.root.join('tmp', 'pids', 'unicorn.pid') File.read(unicorn_pid ).to_i rescue Errno::ENOENT raise "Unicorn does not seem to be running" end end end
起動確認をする。unicornのプロセスが動いていれば設定OK.
% rails unicorn:start unicorn -c /home/gotoh/Sandbox/RailsTest/demo/config/unicorn.rb -E development -D % ps -ef | grep unicorn | grep -v grep gotoh 2403 12 0 16:02 ? 00:00:00 unicorn master -c /home/gotoh/Sandbox/RailsTest/demo/config/unicorn.rb -E development -D gotoh 2405 2403 0 16:02 ? 00:00:00 unicorn worker[0] -c /home/gotoh/Sandbox/RailsTest/demo/config/unicorn.rb -E development -D gotoh 2406 2403 0 16:02 ? 00:00:00 unicorn worker[1] -c /home/gotoh/Sandbox/RailsTest/demo/config/unicorn.rb -E development -D gotoh 2407 2403 0 16:02 ? 00:00:00 unicorn worker[2] -c /home/gotoh/Sandbox/RailsTest/demo/config/unicorn.rb -E development -D gotoh 2408 2403 0 16:02 ? 00:00:00 unicorn worker[3] -c /home/gotoh/Sandbox/RailsTest/demo/config/unicorn.rb -E development -D gotoh 2409 2403 0 16:02 ? 00:00:00 unicorn worker[4] -c /home/gotoh/Sandbox/RailsTest/demo/config/unicorn.rb -E development -D gotoh 2410 2403 0 16:02 ? 00:00:00 unicorn worker[5] -c /home/gotoh/Sandbox/RailsTest/demo/config/unicorn.rb -E development -D
停止する。停止したらプロセスも停止していることを確認する。psの実行結果で何も表示されなければ停止している。
% rails unicorn:stop % ps -ef | grep unicorn | grep -v grep
ログは logs/unicorn.log にある。
バーチャルホストの設定_
今回は
Ubuntu 20.04のnginxは /etc/nginx/sites-avaiable 以下にバーチャルホストの設定を置いておくことになっている。今回のRailsアプリのディレクトリ名がdemoなのでバーチャルホストの設定ファイルもdemoとする。
% sudo touch /etc/nginx/sites-avaiable/demo
root権限で/etc/nginx/sites-avaiable/demoの中身を以下のように編集する。
upstream rails_app { # 注意.unicorn.sockの設置場所のフルパスを記載すること server unix:/home/gotoh/Sandbox/RailsTest/demo/tmp/sockets/.unicorn.sock fail_timeout=0; } server { # ポート番号は任意。 listen 30080; server_name _; # Railsアプリの下にあるpublicディレクトリをrootとする。 root /home/gotoh/Sandbox/RailsTest/demo/public; # このバーチャルホスト用のログを指定する。ファイル名は任意 access_log /var/log/nginx/demo_access.log; error_log /var/log/nginx/demo_error.log; client_max_body_size 100m; error_page 404 /404.html; error_page 500 502 503 504 /500.html; try_files $uri/index.html $uri @unicorn; location / { 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; # upstreamの部分に記載しているもの(今回はrails_app)を書く proxy_pass http://rails_app; } }
設定ファイルを有効化するためには sites-enabled にシンボリックリンクを作成する。
% sudo ln -s /etc/nginx/sites-available/demo /etc/nginx/sites-enabled/demo
設定ファイルが正しいかどうかを設定する。
% sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
nginxを再起動する。
% sudo service nginx restart * Restarting nginx nginx [ OK ]
Railsアプリの起動手順_
以下の手順でWindows上のWebブラウザからRailsアプリにアクセスできる
- nginxを起動する(以下のようになっていたら起動している)
% ps -ef | grep nginx | grep -v grep root 3356 12 0 16:54 ? 00:00:00 nginx: master process /usr/sbin/nginx www-data 3357 3356 0 16:54 ? 00:00:00 nginx: worker process www-data 3358 3356 0 16:54 ? 00:00:00 nginx: worker process www-data 3359 3356 0 16:54 ? 00:00:00 nginx: worker process www-data 3360 3356 0 16:54 ? 00:00:00 nginx: worker process www-data 3362 3356 0 16:54 ? 00:00:00 nginx: worker process www-data 3363 3356 0 16:54 ? 00:00:00 nginx: worker process www-data 3364 3356 0 16:54 ? 00:00:00 nginx: worker process www-data 3365 3356 0 16:54 ? 00:00:00 nginx: worker process (起動していなければ以下のコマンドを実行する) % sudo service nginx start
- Unicornを起動する。
(今回の例の場合は以下のように起動する) % cd ~/Sandbox/RailsTest/demo % rails unicorn:start (確認する) % ps -ef | grep unicorn | grep -v grep gotoh 3416 12 1 16:59 ? 00:00:00 unicorn master -c /home/gotoh/Sandbox/RailsTest/demo2/config/unicorn.rb -E development -D gotoh 3418 3416 0 16:59 ? 00:00:00 unicorn worker[0] -c /home/gotoh/Sandbox/RailsTest/demo2/config/unicorn.rb -E development -D gotoh 3419 3416 0 16:59 ? 00:00:00 unicorn worker[1] -c /home/gotoh/Sandbox/RailsTest/demo2/config/unicorn.rb -E development -D
- Windows上のWebブラウザから http://localhost:30080/people にアクセスする。
トラブルシューティング_
ログ置き場_
nginxのログは以下にある。500 Internal Server Errorや400 Bad Requestなどが出た場合はnginxのログをみる
- /var/log/nginx/demo_access.log, demo_error.log (バーチャルホストのログ)
unicornのログは以下にある。以下のパスは今回の例のもの。
- ~/Sandbox/RailsTest/demo/log/unicorn.log
Railsアプリのログは以下にある。以下のパスは今回の例のもの。
- ~/Sandbox/RailsTest/demo/log/development.log