Kamal2を使ってRails8のアプリケーションをXServerVPSにデプロイする

参考にするのはこちらの記事
XServerにしようと思ったのは、他のアプリケーションでも使ってて、まとめたいから

サーバースペックがどの程度必要かわからないので、とりあえず一番安いやつでやってみる
メモリ:4GB
月額 2,680円~
CPU 4Core
NVMe SSD 200GB

1ヶ月でも約5000円くらいかかるので気軽に試しにくい。。。

取得したいドメインはxserverドメインでは扱いがなかったのでMuuMuuドメインで取得
そういうこともあるのか

ネームサーバーの反映などで数日待ちの状況

Xserverのパケットフィルターの追加から、22ポート(SSH)、80、443ポート(WEB)を開ける

ローカルからSSHキーでのサーバー接続完了

DockerHubにログインし、画面右上のアカウントセッティングからRead&Writeでアクセストークンを作成

このへんでサーバーの設定やらドメイン周りの準備はできたはず。。。?(あとは設定の反映待ち)
(ムームードメインでのDNS設定にミスがあって追加の待ちが発生)

Railsアプリの設定
アプリ自体はRails8で作成済みなので割愛
いろいろ知らないファイルが増えていて面白い
rails-new -u 3.3.6 -r 8.0.0 . --devcontainer

Kamalは静的ファイルを配信するNGINXのようなウェブサーバがありませんので、config/environments/production.rb(GitHub)でconfig.public_file_server.enabled = trueとします。
docker-composeでnginxを立てる構成が多かったように思うけど、Kamalでは立てないと。
理解が弱かったので勉強するなど
静的ファイル配信専用のWEBサーバーがないので、Rails自体にその役割を担わせるのがconfig.public_file_server.enabled = trueの設定
CDNを使えばRailsがそれをやる必要はないが、まぁ今んところはRailsさんに頑張ってもらいましょう

rails-new した段階で.kamalフォルダができていたのでそのまま設定を進める
config/deploy.yml
- service: 自分のサービス名に変更
- image: DockerHubのレジストリは事前作成してないのでサービス名と似たような名前をつける
- servers: web: XserverのVPSのIPアドレスを設定
- proxy: host ドメイン名を設定
- env: secret: これは最初からRAILS_MASTER_KEYが設定済みだった

.kamal/secrets
参考記事にあるように、
KAMAL_REGISTRY_PASSWORDは.kamal/registry_password.keyを読み込むように。(中身はDockerHubのアクセストークン)
RAILS_MASTER_KEY=$(cat config/master.key)は最初からそう設定してあった

Healthcheckの設定についても
config/environments/production.rbのssl_optionsはコメントアウトされた状態だったので特に設定を追加していない

kamal setupを実行してみる
しばらく待つとDockerの組み立てが始まった
エラー発生
------
Dockerfile:49
--------------------
47 |
48 | # Precompiling assets for production without requiring secret RAILS_MASTER_KEY
49 | >>> RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
50 |
51 |
--------------------
ERROR: failed to solve: process "/bin/sh -c SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile" did not complete successfully: exit code: 1

同じエラーについての記事を発見
config.require_master_key = ENV["SECRET_KEY_BASE_DUMMY"].nil?
SECRET_KEY_BASE_DUMMY=1
を追加してみる
んで状況変わらず

RAILS_MASTER_KEYとは?
Railsアプリケーションの機密情報を複合するためのキー
RAILS_MASTER_KEYがないと、本番環境でconfig/credentials.yml.encを読み込めず、アセットプリコンパイルが失敗することがある
じゃあ追加したらいいのでは?
Dockerイメージのビルドで使うとイメージが漏洩したときに機密情報も持っていかれるリスクがある
そこでSECRET_KEY_BASE_DUMMY
ENV["SECRET_KEY_BASE_DUMMY"]を設定すると、一時ファイルに保存されるランダム生成のsecret_key_baseが使われるようになります。これは、ビルド中にproduction用のsecretsにアクセスせずに、production用のアセットをプリコンパイルしたい場合に便利です。

試しにローカルでプリコンパイルしてみることに
RAILS_ENV=production rails assets:precompile
$ RAILS_ENV=production rails assets:precompile
bin/rails aborted!
KeyError: key not found: "OPENAI_ACCESS_TOKEN" (KeyError)
アプリ内で使っている環境変数がプロダクション用に設定できていなかった模様

シークレットキーベースに環境変数を追加し、プリコンパイルが通ることを確認

ふたたびkamal setupするとエラー
------
Dockerfile:38
--------------------
37 | COPY Gemfile Gemfile.lock ./
38 | >>> RUN bundle install && \
39 | >>> rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
40 | >>> bundle exec bootsnap precompile --gemfile
41 |
--------------------
ERROR: failed to solve: process "/bin/sh -c bundle install && rm -rf ~/.bundle/ \"${BUNDLE_PATH}\"/ruby/*/cache \"${BUNDLE_PATH}\"/ruby/*/bundler/gems/*/.git && bundle exec bootsnap precompile --gemfile" did not complete successfully: exit code: 5
手元でdocker build . --progress=plainしてログを調査すると
An error occurred while installing psych (5.2.2), and Bundler cannot continue.

調べてみると以下に当たった
Psych に同梱していた libyaml のソースコードは削除されました。ユーザーは自身で Ubuntu や Debian プラットフォームなら libyaml-dev パッケージをインストールする必要があります。
Dickerfileのapt-get install している部分に追加
libyaml-dev

無事にビルドが完了!

再びkamal setup するもpsychのところで落ちる
と思ったら、Dockerfileの修正をpushしてない!

紆余曲折ありましたが、リリース完了!

kamalコマンドを使ってローカルから色々できる
kamal app exec -i 'bin/rails console'