シングルインスタンスでSQLiteなRails 8アプリをFly.ioにデプロイする
Fly.ioのインスタンス(Machine)の実行時間に応じて課金されます。
そしてauto_stop_machinesを有効にすることで、アプリがアクセスされないときにインスタンスが停止され、その間は課金が発生しません。
(※停止時でもファイルシステム課金は発生します)
またFly.ioはファイルシステム(Volume)をMachineにアタッチできます。
Railsアプリのコンテナ内でredis-serverを起動し、データベースはSQLite3に保存します。
これにより、従来のPaaSよりランニングコストを抑えられ、VPSよりも簡単にデプロイできます。
デメリットとしては、停止時間が発生するため、定期的にジョブを実行するアプリでは停止時間が最大化できなくてコスト効率が悪いです。
またシングルインスタンスなので、複数台に負荷分散するスケールアウトができません。ただし、単一のMachineのスケールアップして1台あたりのスループットを向上することは可能です。
本記事では37signalsが公式に提供しているWritebookというシンプルなCMSのRailsアプリをFly.ioにデプロイします。
まず、writebook.zipをダウンロードして解凍し、ディレクトリに移動します。
次に、Fly.ioの設定ファイルを作成します
fly launch
RAMサイズは1024MBで設定します
app = "<YOUR_APP_NAME>"
primary_region = "nrt" # Tokyo
volumeを作成します。デフォルトの1GBで問題ありません
fly vol create -r nrt -y sqlite3_volume
writebookのドキュメントではDigitalOceanやHetnzerのVPSへのデプロイが推奨されています。
Pumaの前段にThrusterが起動するようになっていますが、Fly.ioでは不要なので剥がします。
gem "bcrypt", "~> 3.1.7"
gem "image_processing", "~> 1.13"
gem "rqrcode"
-gem "thruster"
gem "useragent", github: "basecamp/useragent"
gem "front_matter_parser"
-web: bundle exec thrust bin/start-app
+web: bundle exec puma -C config/puma.rb
[env]
WEB_CONCURRENCY = "1"
PORT = "3000"
[[services]]
internal_port = 3000
protocol = "tcp"
auto_stop_machines = "stop"
auto_start_machines = true
min_machines_running = 0
[[services.ports]]
handlers = ["http"]
port = "80"
force_https = true
[[services.ports]]
handlers = ["tls", "http"]
port = "443"
# Start the server by default, this can be overwritten at runtime
-EXPOSE 80 443
+EXPOSE 3000
CMD ["bin/boot"]
bin/boot
からはProcfileにあるコマンドが同一のコンテナで実行されます
redis-serverとresque-poolがすでに定義されているのでこのままでOKです
外部のredis-serverの追加は不要です
-web: bundle exec thrust bin/start-app
+web: bundle exec puma -C config/puma.rb
web: bundle exec puma -C config/puma.rb
redis: redis-server config/redis.conf
workers: FORK_PER_JOB=false INTERVAL=0.1 bundle exec resque-pool
最後にSQLite3のデータベースをvolumeにマウントします
[env]
WEB_CONCURRENCY = "1"
PORT = "3000"
DATABASE_URL = "sqlite3:///rails/storage/db/production.sqlite3"
[[mounts]]
source = "sqlite3_volume"
destination = "/rails/storage"
production:
primary:
<<: *default
database: <%= ENV['DATABASE_URL'] %>
マイグレーションをデプロイのタイミングで実行するためには、release_commandを利用します
[deploy]
release_command = "bin/rails db:prepare"
Fly.ioにデプロイします
fly deploy
デプロイできました。
サインアップしてCMS機能が一通り動作することを確認します。
その後、auto_stop_machinesが有効になっているので、アクセスがないときはインスタンスが停止されます。
そしてアクセスがあると自動的に起動することを確認します
Discussion