遅まきながら、Vagrant(Virtualbox)でRuby on Railsのローカル環境を構築してみたの巻(その2)

Date:

Share post:

Vagrant(VirtualBox)でのRuby on Railsローカル環境構築ですが、前回は以下を行いました。

  • Webmin + Virtualmin(LEMP)環境作成
  • rbenv,ruby-build,Ruby,Bundler,Railsを仮想ホストのデフォルトユーザディレクトリ(/home/rails-test)配下にインストール

今回は以下を行っていきたいと思います。

  • テスト用のプロジェクト作成
  • Welcomeページ表示
    • ビルトインサーバを使用した場合
    • UNIXドメインソケットを使用してNginxのリバースプロキシを使用した場合(Nginx – puma)

まず、テスト用のプロジェクト(ディレクトリ名をtest_appとします)を作成します。SSHログインし、デフォルトユーザに変更します。

$ su - rails-test
$ cd /home/rails-test
$ mkdir test_app

一旦SSHをログアウトして、Vagrantをシャットダウンします。
その後、共有ディレクトリ設定を変更します。

vagrant halt
【Vagrantfileの抜粋】
         ・
         ・
         ・
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.synced_folder "ホストの共有ディレクトリパス", "/home/rails-test/test_app",
:owner => "rails-test",
:group => "rails-test",
type: "virtualbox", create: true
         ・
         ・
         ・

Vagrantを起動させ、共有ディレクトリが変更されていることを確認します。
その後、SSHログインし、デフォルトユーザに変更します。

$ su - rails-test
$ cd /home/rails-test
$ rails new test_app

テスト用のプロジェクトディレクトリ(test_app)にRailsのファイルが展開されます。

次に、ビルトインサーバでRailsのWelcomeページを表示させたいと思います。
Railsのビルトインサーバのデフォルトポート番号は3000になりますので、一時的にポートを開放して確認します。
Webmin > ネットワーキング > FirewallD から、「許可されたポートを追加します。」ボタンを押下し、
ポート:3000
ネットワークプロトコル:TCP
を追加します。
追加したら、「FirewallDをリロード」ボタンを押下して変更を適用します。

ポートが開放できたら、ビルトインサーバを起動させます。

$ cd /home/rails-test/test_app
$ rails s -b 0.0.0.0
※--binding=0.0.0.0 とすることでホストからアクセスすることを可能にしています。

ビルトインサーバが起動したら以下のような表示がされます。

$ rails s -b 0.0.0.0
=> Booting Puma
=> Rails 7.1.1 application starting in development 
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 6.4.0 (ruby 3.2.2-p53) ("The Eagle of Durango")
* Min threads: 5
* Max threads: 5
* Environment: development
* PID: 11246
* Listening on http://0.0.0.0:3000
Use Ctrl-C to stop

この状態で、仮想ホストのIPアドレスのポート番号3000でアクセスします。
http://XXX.XXX.XXX.XXX:3000/

表示できました。

ビルトインサーバでの表示確認ができましたら、Ctrl-Cで停止します。
確認ができたので、firewallDで開放したポートを閉じます。
Webmin > ネットワーキング > FirewallD から、追加したポート3000にチェックをして、「選択したルールを削除」ボタンを押下して削除します。削除したら、「FirewallDをリロード」ボタンを押下して変更を適用します。

ビルトインサーバでの表示確認はできましたが、実際の運用の場合に都度ビルトインサーバ(以降はpumaと記載)を起動させなければいけないのは不便かと思いますので、UNIXドメインソケットを使用してNginxのリバースプロキシを使用した形に変更をしたいと思います。

LEMP環境でNginxサーバは準備ができている状態になりますが、以下のような形への変更となります。

Nginxで受けたHTTPリクエストをpumaに渡します。
↓
pumaは受け取ったリクエストをRack(Railsとのインターフェース)が分かるデータ形式で渡します。
↓
Rackはルールに基づいてRailsを呼び出します

まず、UNIXドメインソケットを作成します。
/home/rails-test/test_app/config にある、puma.rb を修正します。

【/home/rails-test/test_app/config/puma.rbの抜粋】
          ・
          ・
          ・
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#port ENV.fetch("PORT") { 3000 }
shared_dir = "/home/rails-test/puma_shared"
bind "unix://#{shared_dir}/sockets/puma.sock"
          ・
          ・
          ・

pumaのデフォルトポート:3000でlistenしてしまうので、コメントアウトしています。
次の行でUNIXドメインソケットを作成してbindしていますが、注意点があります。
もともとは、ホストとの共有ディレクトリ内にUNIXドメインソケットを作成しようとしたのですが、共有ディレクトリの実行権限のせいからかうまくできませんでした。そのため、共有ディレクトリ外にソケットを作成するように変更しました。

変更前:/home/rails-test/test_app/tmp/sockets/puma.sock(共有ディレクトリ内)
変更後:/home/rails-test/puma_shared/sockets/puma.sock(共有ディレクトリ外)

次に、Nginxの設定にUNIXドメインソケットに関する設定を追記していきます。

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;

worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    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;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2;
#        listen       [::]:443 ssl http2;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

     server_names_hash_bucket_size 128;
     #ここから追加①
     upstream backend {
  	server unix:/home/rails-test/puma_shared/sockets/puma.sock;
     }
     #ここまで

     server {
	server_name rails-test.com www.rails-test.com mail.rails-test.com;
	listen XXX.XXX.XXX.XXX;
	root /home/rails-test/test_app/public;
	index index.php index.htm index.html;
	access_log /var/log/virtualmin/rails-test.com_access_log;
	error_log /var/log/virtualmin/rails-test.com_error_log;
	fastcgi_param GATEWAY_INTERFACE CGI/1.1;
	fastcgi_param SERVER_SOFTWARE nginx;
	fastcgi_param QUERY_STRING $query_string;
	fastcgi_param REQUEST_METHOD $request_method;
	fastcgi_param CONTENT_TYPE $content_type;
	fastcgi_param CONTENT_LENGTH $content_length;
	fastcgi_param SCRIPT_FILENAME "/home/rails-test/public_html$fastcgi_script_name";
	fastcgi_param SCRIPT_NAME $fastcgi_script_name;
	fastcgi_param REQUEST_URI $request_uri;
	fastcgi_param DOCUMENT_URI $document_uri;
	fastcgi_param DOCUMENT_ROOT /home/rails-test/public_html;
	fastcgi_param SERVER_PROTOCOL $server_protocol;
	fastcgi_param REMOTE_ADDR $remote_addr;
	fastcgi_param REMOTE_PORT $remote_port;
	fastcgi_param SERVER_ADDR $server_addr;
	fastcgi_param SERVER_PORT $server_port;
	fastcgi_param SERVER_NAME $server_name;
	fastcgi_param PATH_INFO $fastcgi_path_info;
	fastcgi_param HTTPS $https;
	location ^~ /.well-known/ {
		try_files $uri /;
	}
	location ~ "\.php(/|$)" {
		try_files $uri $fastcgi_script_name =404;
		default_type application/x-httpd-php;
		fastcgi_pass unix:/var/php-fpm/169865842526435.sock;
	}

        #ここから追加②
  	location / {
    		try_files $uri @app;
  	}

	location @app {
    		proxy_set_header    Host                $http_host;
    		proxy_set_header    X-Real-IP           $remote_addr;
    		proxy_set_header    X-Forwarded-Host    $host;
    		proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    		proxy_set_header    X-Forwarded-Proto   $scheme;
    		proxy_pass http://backend;
  	}
        #ここまで

	fastcgi_split_path_info "^(.+\.php)(/.+)$";
	location /cgi-bin/ {
		gzip off;
		root /home/rails-test/cgi-bin;
		fastcgi_pass unix:/var/fcgiwrap/169865842526435.sock/socket;
		fastcgi_param SCRIPT_FILENAME "/home/rails-test$fastcgi_script_name";
		fastcgi_param GATEWAY_INTERFACE CGI/1.1;
		fastcgi_param SERVER_SOFTWARE nginx;
		fastcgi_param QUERY_STRING $query_string;
		fastcgi_param REQUEST_METHOD $request_method;
		fastcgi_param CONTENT_TYPE $content_type;
		fastcgi_param CONTENT_LENGTH $content_length;
		fastcgi_param SCRIPT_NAME $fastcgi_script_name;
		fastcgi_param REQUEST_URI $request_uri;
		fastcgi_param DOCUMENT_URI $document_uri;
		fastcgi_param DOCUMENT_ROOT /home/rails-test/public_html;
		fastcgi_param SERVER_PROTOCOL $server_protocol;
		fastcgi_param REMOTE_ADDR $remote_addr;
		fastcgi_param REMOTE_PORT $remote_port;
		fastcgi_param SERVER_ADDR $server_addr;
		fastcgi_param SERVER_PORT $server_port;
		fastcgi_param SERVER_NAME $server_name;
		fastcgi_param PATH_INFO $fastcgi_path_info;
		fastcgi_param HTTPS $https;
	}
	listen XXX.XXX.XXX.XXX:443 ssl;
	ssl_certificate /home/rails-test/ssl.cert;
	ssl_certificate_key /home/rails-test/ssl.key;
	}
}

①がUNIXドメインソケットに係る設定、②がリバースプロキシに係る設定となります。
設定ができたら、Nginxを再起動します。

次にpumaを起動させます。

$ cd /home/rails-test/test_app
$ bundle exec puma
Puma starting in single mode...
* Puma version: 6.4.0 (ruby 2.7.8-p225) ("The Eagle of Durango")
* Min threads: 5
* Max threads: 5
* Environment: development
* PID: 21401
* Listening on unix:///home/rails-test/puma_shared/sockets/puma.sock
Use Ctrl-C to stop

先ほどのビルトインサーバ起動の時と異なり、UNIXドメインソケットでListenしているのがわかります。
ソケット作成場所を確認してみます。

$ cd /home/rails-test/puma_shared/sockets
$ ls -l
srwxrwxrwx 1 rails-test rails-test 0 Nov 1 11:52 puma.sock

できていますね。

http://XXX.XXX.XXX.XXX/ でWelcome画面が表示されると思います。

UNIXドメインソケットでListenできるようになったら、一旦pumaをCtrl-Cで停止します。
次にpumaを常時起動させるために、systemdにユーザーサービスとして登録を行います。
Webmin > システム > 起動とシャットダウン でサービスの一覧が表示されますので、「新しいsystemdサービスを作成します。」を押下します。

サービス名:puma
サービスの説明:Rails APP Server
起動時に実行するコマンド:/home/rails-test/.rbenv/shims/bundle exec puma
起動時に起動しますか?:はい

上記を設定、入力し「作成」ボタンを押下すると puma.service というユーザーサービスが作成されます。
ただ、このままではpumaを起動しても起動されませんので、設定の追記をします。
一覧のpuma.service をクリックするとシステム構成として設定が表示されますが、以下のようになっていると思います。

[/usr/lib/systemd/system/puma.service(変更前)]
[Unit]
Description=Rails APP Server
[Service]
ExecStart=/home/rails-test/.rbenv/shims/bundle exec puma
[Install]
WantedBy=multi-user.target

これを以下のようにします。

[/usr/lib/systemd/system/puma.service(変更後)]
[Unit]
Description=Rails APP Server
After=network.target ← network関連サービス起動後に実行
[Service]
User=rails-test ← 仮想ホストのデフォルトユーザ権限で実行する
WorkingDirectory=/home/rails-test/test_app ← 実行ディレクトリの指定
ExecStart=/home/rails-test/.rbenv/shims/bundle exec puma
Restart=always ← システム起動時に常時実行する
[Install]
WantedBy=multi-user.target

「今すぐ開始」ボタンを押下して実行されるかを確認します。右下に表示される、現在の状態が実行中になれば大丈夫です。
補足ですが、以下コマンドを実行するとサービスの依存関係が一覧で表示されます。

# systemctl list-dependencies

ユーザーサービスとしてpumaが起動できたら、再度
http://XXX.XXX.XXX.XXX/ でWelcome画面が表示されると思います。

ただ、上記サービス設定の場合、pumaはdevelopmentモードで起動しています。

次回は

・URLをIPアドレスから仮想ホストのドメイン表示に変更
・環境切り替えについて(さわりですが)

を行いたいと思います。

Related articles

我流Flutter学習ステップ(6)スマホでの動作...

本シリーズ(?)の最初の投稿で書いた...

その「平均値」に意味はあるのか?

最近「平均」に関して思うところがあっ...

遅まきながら、Vagrant(Virtualbox...

前回は、pumaを常時起動のユーザーサ...

遅まきながら、Vagrant(Virtualbox...

今までPHPを主な案件としておりました...