こんにちは!maimuです。
私が参加しているプロジェクトでは、複数のRailsアプリケーションが稼働しています。デプロイの方法として Docker Compose で対応をしていましたが、夜間にデプロイ作業をする必要があり、毎回タイミングの調整作業が発生していたため、ゼロダウンタイムでデプロイが可能なKamalに移行することになりました。
Kamal でデプロイを実行する場合、Rails アプリケーションのデータベースに SQLite を利用していたり、その他のミドルウェアを必要としない場合は設定ファイルは初期設定を少し編集するのみで対応ができます。 しかし、実際にサービスとして利用されているアプリケーションの多くは構成がもっと複雑であり、Kamal の設定においても状況に応じて考慮すべき点が変わっていきます。
今回のデプロイ方法の移行を通じて学んだ Kamal の設定部分に焦点を当てて、こちらのブログ記事をまとめていきたいと思います。 また、対象のプロジェクトは公開リポジトリであるため、以下から内容をご確認いただくことが可能です。
deploy.yml の設定について
全セクションに触れると内容が膨大になってしまうため、Kamal のドキュメントを読んだ際に自分が情報として把握しておきたかった部分を中心に触れたいと思います。
環境ごとにデプロイ先を分ける
Kamal の初期セットアップはドキュメントに記載があるため、ここでは割愛します。
初期セットアップ後の deploy.yml の設定変更について見ていきたいと思います。 対象のプロジェクトは本番環境とステージング環境があるため、それぞれデプロイ先を分ける必要があります。 その場合は、設定の共通部分を deploy.yml にまとめ、差分がある部分を deploy.production.yml や deploy.staging.yml にまとめていきます。 その際、deploy.yml に以下のように指定をすることで明示的にデプロイ先を指定しない限りデプロイできないようにするセーフガード設定をすることができます。
service: mssform image: w3const/mssform require_destination: true # セーフガードの設定
実際のデプロイ時は -d フラグでデプロイ先を指定して実行します。
$ kamal deploy -d staging
builder セクションについて
builder セクションには、まず arch セクションがあり、初期セットアップの時から amd64 が指定されています。
ARM64(Apple Silicon のような)上で開発をしていて、AMD64(x86 64ビット)でデプロイする場合に必要な設定です。
builder セクションに args セクションを追加すると、Dockerfile のビルド時のみ有効な変数 ARG に渡す引数を指定することができます。
今回は以下のように APP_GID と APP_UID を指定し、権限エラーが起きないように対応しています。
builder: arch: amd64 args: APP_GID: xxxxx # グループIDを指定する APP_UID: xxxx # ユーザーIDを指定する
このほかにも環境ごとに異なる引数を指定したい場合は、その内容を deploy.*.yml の builder: セクションに指定することで対応ができます。
env セクションについて
Kamal を初期セットアップした際に .kamal/secrets-common が生成され、環境変数の雛形として使用されます。
環境ごとにデプロイ先を分けている場合は .kamal/secrets.production 、secrets.staging のように固有の環境変数を分けて管理します。
deploy.yml ではenv セクションの secret セクションに秘匿にしておく必要がある情報を記載し、それ以外を clear セクションに記載して管理します。
volumes セクションについて
リモートサーバー上の指定したパスをDockerコンテナにマウントします。 deploy.yml には本番やステージング環境を問わず同じ設定になるものを書き、環境ごとに異なる設定はそれぞれの deploy.*.yml に書いて管理します。
aliases セクションについて
Kamal の CLI コマンドにエイリアスを付けて、ショートカットコマンドを定義している箇所です。
こちらは初期セットアップから変更していません。
このエイリアスのおかげで、例えばターミナル上で kamal console と打つと bin/rails console をリモートのコンテナ内で起動することができます。
aliases: console: app exec --interactive --reuse "bin/rails console" shell: app exec --interactive --reuse "bash" logs: app logs -f dbc: app exec --interactive --reuse "bin/rails dbconsole"
accessories セクションについて
Rails アプリが依存する周辺ツールをKamal 経由で起動・管理できるようにするためのセクションです。 この部分がアプリケーション固有の内容が含まれていたりで、設定の内容が難しい部分でした。 例えば、プロジェクトではオブジェクトストレージサーバーとして MinIO を利用しています。 accessories セクションでの設定は以下のようになります。
accessories: minio: image: minio/minio:RELEASE.2025-04-03T14-56-28Z cmd: server /data proxy: app_port: 9000 healthcheck: path: /minio/health/live options: user: 2233:11370 env: secret: - MINIO_ROOT_USER - MINIO_ROOT_PASSWORD clear: TZ: Asia/Tokyo
各セクションについて触れていくと
imageセクションは使用するDockerイメージを指定cmdセクションは MinIO を/dataディレクトリをストレージルートとして起動するための指示proxyセクションは MinIO に対して一般ユーザのブラウザからリバースプロキシ経由でアクセスできるようにする設定app_portセクションは9000ポートをリバースプロキシで公開するための設定healthcheckセクションは/minio/health/liveにアクセスして、MinIO が稼働中かどうかをチェックするための設定
optionsセクションはアプリ本体と同じユーザー権限に揃えるための設定
env セクションは本体の設定と説明は同様になります。
状況によっては Docker イメージが Docker Hub 以外で公開されている場合があります。
その場合は image セクションに加えて、以下のようにregistry セクションを設定する必要があります。
registry: server: ghcr.io username: - GHCR_USERNAME password: - GHCR_PASSWORD
デプロイ方法の移行作業について振り返り
デプロイ方法を Kamal へ移行するにあたって、deploy.yml の設定内容を中心に調べながらの対応となりました。
accessories セクションの箇所で触れた通り、アプリケーションが依存するミドルウェアの内容を自分がきちんと把握できていなかったことが原因で設定をどう進めればいいかがうまく調べられないこともありましたが、今回の作業を通してアプリケーションの全体像を理解するきっかけをもらうことができました。
また、対象のプロジェクトはスパコン上でRailsアプリケーションが稼働しており、調査や作業をする際に毎回サーバーに入ってDockerコマンドを実行する必要がありました。 始めに Kamal への移行することのきっかけとしてゼロダウンタイムデプロイを挙げましたが、Kamal でデプロイするようにしたことで Kamal CLI コマンドが利用できるようになったため、サーバーに入って作業する手間が軽減するという効果もありました。
Kamal についてはまだまだ情報が多くないと感じており、今回のブログ記事が Kamal 導入のなんらかの手掛かりになることがあれば嬉しいです。 また、継続的に運用をしていく中で新たな気づきがある際はそれについても発信していけたらと考えています。
永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと成長したいエンジニアを絶賛募集しています。