【Rails8】”Kamal2″ を用いてクラウドへデプロイしてみた

Rails 8 から新たに導入された「Kamal2」。

Docker コンテナを利用し、とても簡単にデプロイできるため、検証を兼ねて Rails 8で作成したアプリケーションをKamal 2を用いてデプロイしてみた。

本記事では、備忘録を兼ねて、その手順と気づきをアウトプットする。

前提条件

本記事における前提条件は以下のとおりだ。
アプリケーションのソースコードは、GitHub で管理している。

ローカル環境

  • OS:Mac OS 15.6.1
  • Ruby v3.4.7
  • Rails v8.0.3
  • データベース:SQLite3
  • Kamal v2.7.0
  • Docker v4.52.0

サーバー環境

  • クラウド:さくらのVPS
  • OS:AlmaLinux v10 x86_64
    ※SSHでログイン可能な状態に設定しておくこと

サーバーを準備する

VPSを準備する

VPSの準備については省略する。
「さくらのVPS」は以下リンク先から利用できる。プランは公開するアプリケーションの要件や用途に合ったものを選択する。

VPS(仮想専用サーバー)|さくらインターネット
さくらのVPS(仮想専用サーバー)のご案内です。全プランSSD対応・root権限付き!

運用上の注意

セキュリティ面を考慮し、さくらの VPS の「パケットフィルター」機能を利用し、不要なポートを閉じ、通信制限を行うことを推奨する。

「パケットフィルター」機能の利用方法については、以下のマニュアルを参照。

パケットフィルター
目次: 注意事項, 利用方法- パケットフィルターの有効化, パケットフィルターの無効化, パケットフィルター設定の削除, 旧バージョンのカスタム設定と同じように使うには., Q&A. 「パケッ...

サーバーにSSHで接続する

VPS に Mac 側で生成した SSH 公開鍵を登録し、サーバーへローカルから SSH で接続できるようにする。
手順は以下のマニュアルを参照。
https://manual.sakura.ad.jp/vps/controlpanel/ssh-keygen.html

公開鍵を追加した後、ターミナルから SSH でサーバーへ接続できることを確認する。

% ssh root@VPSのIPアドレス

以下のように表示されればOK。

[root@ホスト名 ~]# 

サーバーにDockerをインストールする

以下のコマンドを実行。

# sudo dnf update -y && sudo dnf install -y dnf-plugins-core && sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin && sudo systemctl start docker && sudo systemctl enable docker

Dockerがインストールされたことを確認する。
バージョンが表示されれば成功だ。

# docker --version
Docker version 29.0.2, build 8108357

デプロイ用のユーザーを作成する

rootとは別に、デプロイ用のユーザーを作成する。(例:ユーザー名を「deploy」とする場合)

sudo useradd -m -s /bin/bash deploy && sudo usermod -aG docker deploy && echo "deploy ALL=(ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoers

作成したユーザーにパスワードを設定する。

sudo passwd deploy

作成したユーザーでSSH接続できることを確認する。

% ssh deploy@VPSのIPアドレス
deploy@VPSのIPアドレス's password: 
Last login: ------
[deploy@ホスト名 ~]$ 

以上でサーバー側の準備は終了。

デプロイの準備をする

ローカルに Docker をインストールする

Kamal 2 によるデプロイでは Docker コンテナを利用するため、Docker が未インストールの場合は事前にインストールしておく。

※なお、記事作成時点では、アプリケーションの開発環境で Docker を利用していなくても問題なくデプロイできた。

インストールは以下リンク先を参照。
https://www.docker.com/ja-jp/

ローカルに Docker をインストールしない場合

デプロイ時に以下のエラーが出る。

ERROR (Kamal::Cli::DependencyError): Docker is not installed locally

config/deploy.ymlを編集する

config/deploy.yml には、Kamal 2 を用いてデプロイする際の設定を記入する。
なお、本ファイルはすべて小文字で記入すること。(大文字で記載するとエラーが出る)

# config/deploy.yml

service: リポジトリ名
image: GitHubユーザー名/アプリケーション名

servers:
  web:
    hosts:
      - xxx.xxx.xxx.xxx   # ← VPSのIPアドレス

registry:
  server: ghcr.io
  username: GitHubユーザー名    # ← GitHubユーザー名
  password:
    - KAMAL_REGISTRY_PASSWORD

ssh:
  user: deploy   # ← 作成したデプロイ用のユーザー名

env:
  clear:
    RAILS_ENV: production
  secret:
    - RAILS_MASTER_KEY

proxy:
  ssl: true
  host: ドメイン名   # ← 使用するドメインを入力する

builder:
  arch: amd64

volumes:
  - "storage:/rails/storage"
  - "db:/rails/db"

asset_path: /rails/public/assets

ドメインを用いない場合

ステージング環境等で、ドメインを用いない場合は proxy の部分を以下のように記載する。

proxy:
  ssl: false       
  host: xxx.xxx.xxx.xxx   # ← VPSのIPアドレス

.kamal/secrets を編集する

前述の config/deploy.yml で使用する環境変数を .kamal/secrets に設定する。
GitHubで管理する場合、本ファイルは .gitignore に記載すること。

# GitHubのアクセストークン
KAMAL_REGISTRY_PASSWORD="ghp_xxxxxxxxxxxx"

# Rails Master Key
RAILS_MASTER_KEY=$(cat config/master.key)

# Secret Key Base
# rails secret で生成された値を貼り付ける
SECRET_KEY_BASE="yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"

記載後、入力内容を読み込ませる。

% source .kamal/secrets

すべての環境変数が反映されていることを確認する。

echo $KAMAL_REGISTRY_PASSWORD

echo $RAILS_MASTER_KEY

echo $SECRET_KEY_BASE

GitHub アクセストークンの発行方法

以下リンク先から発行し、出力された値を上記ファイルへ貼り付ける。
権限は「write:packages」と「read:packages」にチェックを入れる。
https://github.com/settings/tokens

Kamal の設定を検証する

以下コマンドで、設定ファイルに問題がないか検証する。
エラーが出なければOK。

% kamal config

エラーの例

Builder が記載されていない
% kamal config
  ERROR (Kamal::ConfigurationError): builder: Builder arch not set
Docker のメール認証が未実施
ERROR: failed to build: Error response from daemon: authentication required - email must be verified before using account
docker stderr: Nothing written
config/deploy.yml のリポジトリ名に大文字が含まれている
ERROR: failed to build: invalid tag "ghcr.io/GitHubユーザー名/アプリケーション名:fb3850f459c732813fb65f2613e4771be1a92ab4": repository name must be lowercase
docker stderr: Nothing written

サーバーを初期化する

デプロイ先サーバを Kamal が扱える状態に初期化する。
本手順を踏むことで「kamal deploy」や「kamal rollback」などのコマンドが使用できるようになる。

% kamal server bootstrap

デプロイをする

ここまでで準備完了。いよいよ初回デプロイを実施する。

初回セットアップ

以下コマンドで初回セットアップを実施。
本コマンドを実行時、完了まで約10分程度を要した。

% kamal setup

実行内容

1. Dockerイメージのビルド

2. GitHubにプッシュ

3. サーバーにデプロイ

4. データベースのセットアップ(SQLiteファイル作成)

5. マイグレーション実行

6. アセットのプリコンパイル

7. コンテナの起動

遭遇したエラー

初回実行時、以下のエラーに遭遇した。

ERROR (SSHKit::Command::Failed): Exception while executing on host VPSのIPアドレス: docker exit status: 1
docker stdout: Nothing written
docker stderr: Error: target failed to become healthy within configured timeout (30s)

以下コマンドでログを確認したところ、Rails 側に原因があった。

% kamal app logs --lines 100

原因を除去のうえ、再デプロイ。
エラーが出ずにデプロイできた。

アプリケーションの状態を確認する

以下のコマンドを実行し、特にエラーが出ていなければOK。

% kamal app logs

コンテナの一覧を確認する

本番環境でアプリケーションを起動しているコンテナを確認する。

% kamal app containers

INFO [029ed03d] Running docker container ls --all --filter label=service=アプリケーション名 --filter label=destination= on VPSのIPアドレス

デプロイが成功したことを確認する

ブラウザで ドメイン、または VPS の IP アドレスを実行し、アプリケーションが表示されることを確認する。

https://ドメイン名
http://VPSのIPアドレス

※ドメインを設定する場合、あらかじめゾーン設定を行っておくこと。( A レコードを VPS の IP アドレスに設定する)

リアルタイムでアプリケーションのログを確認する

アプリケーションが表示されたら、動作確認をする。
以下コマンドを実行し、エラーが出ないことを確認する。

% kamal app logs --follow

2 回目以降のデプロイ手順

2 回目以降は、変更を GitHub へ push した後、以下のコマンドを実行するのみでOK。

% kamal deploy

よく使うコマンド

アプリケーションの管理

デプロイ

% kamal deploy

ロールバック

% kamal rollback

再起動

% kamal app restart

停止

% kamal app stop

起動

% kamal app start

削除

% kamal app remove

Rails コンソールの起動

% kamal app exec --interactive --reuse "bin/rails console"

本番環境でのマイグレーション実行

% kamal app exec "bin/rails db:migrate"

本番環境でのロールバック

% kamal app exec "bin/rails db:rollback"

本番環境での seed 実行

% kamal app exec "bin/rails db:seed"

SQliteファイルのバックアップ

% kamal app exec "cat /rails/db/production.sqlite3" > backup_$(date +%Y%m%d_%H%M%S).sqlite3

バックアップからのリストア

cat backup_xxxxxx_yyyyyy.sqlite3 | kamal app exec --interactive "cat > /rails/db/production.sqlite3"

アプリケーションの状態確認

アプリケーションの状態

% kamal app details

コンテナの一覧

% kamal app containers

バージョン確認

% kamal app version

感想

従来のデプロイ方法(サーバ内部に Web サーバ、Ruby、Rails、データベースなどをインストールして行う方法)と比較すると、とても簡単にデプロイできた。

特に、複雑なセットアップ作業から解放され、アプリを動かすまでの手順が明確になったことで、デプロイに対する心理的ハードルが大きく下がった。Kamal 2 の利便性を実感できる良い経験になった。

参考資料

タイトルとURLをコピーしました