Railsアプリを公開しようとAWS EC2 に無料枠立てられるインスタンスで環境構築を試みた。
しかし、rbenv経由のrubyビルドでディスク容量不足になってしまった。
Fargateなど使う選択肢もあったのだが、なるべく安く済ませたかったので探したうえでRenderを使うことにした。
これを記録的に共有したい。
Renderは無料枠があり、それを使う。
Herokuの課金体系が変わった際には、Renderに乗り換えるという方が多かった様子であった。
参考
導入
ローカル構築
以下のdocker-compose.yml dockerfile を用意する。
1 | version: "3" |
1 | FROM ruby:3.5-rc |
でDockerイメージをビルドして起動する。
以下shellで入って実行。
1 | $ bundle init |
ここまでで初期化完了、適当に1つモデルを追加する。
1 | $ bundle exec rails generate scaffold Product name:string description:text price:decimal |
で起動すると /products が生えていている。一旦OK。
Render用の構築
Renderでは、データベースはPostgreSQLを使うことなる。
そのため、databaseをPostgreSQLに変更する。
1 | $ bundle exec rails db:system:change --to=postgresql |
database.yml を以下のように変更する。(本来は環境変数であるところも一度べた書き、実際は環境変数)
1 | default: |
一旦docker を停止し、以下をDockercomposeに追加する。
1 | pgdb: |
改めてbuildしなおす。
1 | $ docker-compose build |
1 | $ bundle install |
これでpostgresに接続したので起動できることを確認。
また、資料には solid は初期導入の簡素化のために外して個別に入れて欲しい旨の記載がある。
既にアプリは作成済みのため、以下の項目はコメントアウトしておく。
1 | #gem "solid_cache" |
この状態で、bundle install
しておく。
Renderにデプロイ
Renderにアカウントを作成し Web Services
から追加する。
githubから連携できるので連携する。
言語の選択などあるので、ruby を選択したりする。
一旦deployをするがエラーになるので、以下を対応していく。
bin/render-build.sh を作成する。ドキュメントのままコピーする
1 | #!/usr/bin/env bash |
作った後、必ず権限をつけること。
これが無いと実行できなくてコケることになる。
1 | $ chmod a+x bin/render-build.sh |
bin/rails の権限も必要なので、同様に変更する。
1 | $ chmod a+x bin/rails |
自身の環境ではこれも効果が無く、git update-index --chmod=+x bin/render-build.sh
のように権限を変更した。
どうやらWindows環境である場合には、この対処が必要な模様。
これをcommitしてpushする。
これがまたコケる。
設定画面からBuild Commandを bin/render-build.sh
に変更する。
まだ、デプロイできない。
このアプリケーションはRuby 3.5.0 で用意したが、Renderのデフォルトは3.4.4(2025/08/23現在)。
対応バージョンが無いために失敗するので、3.4.4に変更する。
1 | ruby-3.4.4 |
続けてsecret key baseの設定が不足している指摘が入るので、環境変数に SECRET_KEY_BASE
を追加し、bin/rails secret
の結果を設定する。
併せて RAILS_ENV=production
も設定する。
ここまで設定してデータベースの参照が無いことをへのエラーが入る。
データベースの設定をする。
RenderのPostgreSQLを使う
Render のダッシュボードから Add New
-> Postgres
を選択し、PostgreSQLのインスタンスを作成する。
名称は任意に設定する。Dataase
の項目は、はじめアプリが参照する名前と一致するため app_production
としたが、接尾辞が付与されてしまったので究極なんでもよいと考えられる。
少し待つと作成が完了する。画面を下ると、各種設定の記載があるので、これを環境変数に設定する。
Renderの設定項目 | 環境変数名 |
---|---|
Internal Database URL | DATABASE_URL |
併せて、database.yml の記載も以下のように直す。
1 | default: |
1 | NoMethodError: undefined method 'solid_queue' for an instance of Rails::Application::Configuration (NoMethodError) |
のようにログが出る。
対応として、Gemfile から solid 関連をコメントアウトしたが利用側が残っているので暫定的にコメントアウトする。
1 | # Replace the default in-process memory cache store with a durable alternative. |
ここまで実施してデプロイは完了するが、404エラーになる。
原因は、config/environments/production.rb
の config.hosts
にホスト名が設定されていないため。これを書き換える。(環境変数で設定の方が望ましいはず。)
1 | config.action_mailer.default_url_options = { host: "hogehoge.onrender.com" } |
これで、無事にRailsアプリがRender上で動作した。
データベースを外部に切り替える
RenderのPostgreSQLは、無料枠があるものの、期間が設定されていることからデータべ――スを外部に切り替えてみます。
今回はNEON。
これは、NEON から文字列を取得し、Renderの環境変数DATABASE_URL
に設定するだけでよい。
cron の実行
定期的に実行したい処理がある。
RailsアプリならWheneverのようなものを使いたいが、Renderではcron自体は使えない。
それは実行とビルドの環境が異なることに起因する。
Renderでは、Cron Jobという機能があるが、無料で使えない。
rubyのgemはサードパーティであればあるのだが、受信側の実装が無い。
リクエストの真正性の問題があるが、一旦これを使う。
到達する先のコントローラーは次のようにする。
1 | class JobsController < ApplicationController |
リクエストには、UpstashのスケジュールIDが含まれるので、最低限それを突き合わせる選択肢はあり得る。
(そもそもちゃんと公式のReceiverのような検証すべき。)
「前回実行からxx分経っている」を実行条件にすると仮に連打されても問題は一定程度回避できる。
非常に長いタスクであれば難しい面はあろうが、メッセージを切り替えることくらいでああれば対応できることが見込まれる。
Rails アプリをRender.comにデプロイして、疑似的なCronジョブを実行まで試みました。
ここまで出来れば、かなりサービス運営として十分稼働でできる所感を得られました。
では。