技術8 阅读

私が使っているVPSデプロイの神ツール Kamal2 入門ガイド

現在、私が使っているフルスタックフレームワークは主にNext.js 16とRails 8です。Railsを使うことで、公式推奨のデプロイツールKamalに触れる機会がありました。普段はRNとAlibaba Cloudサーバー上でプロジェクトをデプロイする際に使っています。使い勝手が良くシンプルなので、今回はKamal2の概念と入門的な使い方をご紹介しようと思います。

この記事では最初から難しい内容は扱いません。むしろ、Kamal2の最も核となる部分をわかりやすく説明したいと思います。具体的には、それが何か、私たちに何ができるのか、基本的な始め方、そして普段よく使う操作についてです。最後に、Next.jsのユースケースを紹介し、前述の概念を具体的なプロジェクトに落とし込む手助けをします。

Kamal2とは何か

一言でまとめると、Kamal2は **SSH + Docker を使ってアプリケーションをデプロイするためのツール** です。Herokuのような完全なプラットフォーム機能を提供するわけでもなく、Kubernetesのような重量級のオーケストレーションシステムでもありません。むしろ、「一連のDockerコンテナをデプロイする」という作業を、繰り返し実行可能なコマンドと設定としてまとめたものです。

Kamalの核となる考え方は非常にシンプルです:

これは私が Kamal を気に入っている点でもあります。余計な抽象化が少なく、何をしているのかがおおよそ理解できるので、問題が発生したときも調査しやすいです。

Kamal2 が適しているシーン

Kamal は次のようなケースに特に適していると思います:

言い換えれば、Kamal は Docker を「代替」するのではなく、Docker のデプロイをもっと使いやすくするためのものです。

まずはいくつかの基本概念を理解する

始める前に、Kamal で最も重要な概念をいくつか覚えておくことをお勧めします。

config/deploy.yml

これは Kamal のメイン設定ファイルで、デプロイ設定はここから読み込まれます。「今回のデプロイの説明書」のようなものです。サービス名、イメージ名、サーバーリスト、イメージレジストリ、環境変数、ビルダー、プロキシなどの内容がここに書かれます。

.kamal/secrets

これは secrets ファイルのデフォルトの場所で、Kamal はここから機密変数を読み取ります。例えば、イメージレジストリのパスワードや、Rails の RAILS_MASTER_KEY などは、通常 deploy.yml に直接ハードコードせず、.kamal/secrets を通じて注入します。

kamal setup

これは初回デプロイで最も重要なコマンドです。ドキュメントには明確に書かれていますが、サーバーに接続し、Docker がなければインストールし、イメージレジストリにログインし、イメージをビルド・プッシュ・プルし、kamal-proxy を起動し、新しいコンテナを起動し、GET /up200 OK を返した後にトラフィックを切り替えます。

kamal deploy

これはその後のリリースで最もよく使われるコマンドです。初回の setup が成功した後は、通常 kamal deploy でデプロイを完了します。

Kamal2 のインストール方法

ローカルにすでに Ruby 環境がある場合、最も直接的なインストール方法は次の通りです:

bash
gem install kamal

これは公式ドキュメントで示されている標準的なインストール方法です。Ruby がない場合は、Docker 化された Kamal を実行することもできますが、公式ではこの方法にはいくつかの制限があると明記されているため、入門段階では gem インストールをお勧めします。

インストールが完了したら、バージョンを確認できます:

bash
kamal version

プロジェクトの初期化

プロジェクトのディレクトリに移動し、次のコマンドを実行します:

bash
kamal init

このコマンドは、Kamal に必要な基本ファイルを初期化します。最も重要なのは config/deploy.yml.kamal/secrets です。

もしプロジェクトにすでに Dockerfile があれば、それは非常に重要な前提条件を満たしていることになります。Kamal のデフォルトのデプロイフローは、プロジェクトのルートにある標準的な Dockerfile を中心にイメージをビルドします。

最小限の設定

入門時は、まず小さな config/deploy.yml から始めることをお勧めします。公式ドキュメントの最小限の例は次のようなものです:

yaml
service: myapp
image: your-registry-user/myapp

servers:
  - 203.0.113.10

registry:
  username: your-registry-user
  password:
    - KAMAL_REGISTRY_PASSWORD

builder:
  arch: amd64

env:
  secret:
    - AUTH_SECRET

この設定の中で、最初に理解すべき項目は以下の通りです:

この段階では、設定を完全にしようと追求せず、まずは基本的なパスが動くことを確認する方が重要です。

secrets の設定

次に .kamal/secrets を準備します。例:

bash
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
AUTH_SECRET=your-auth-secret

Rails プロジェクトの場合、ドキュメントの例では config/master.key から RAILS_MASTER_KEY を読み取ります。これも Rails と Kamal が自然に統合する理由のひとつです。Rails の新規プロジェクトはもともとこのデプロイ方法を導入しやすいからです。

初回デプロイで何が起こるか

設定と secrets の準備ができたら、次のコマンドを実行します:

bash
kamal setup

このコマンドは多くのことを行いますが、「完全な初回デプロイ」と理解できます。公式ドキュメントによると、少なくとも以下のアクションを実行します:

  1. SSH でサーバーに接続。

  2. サーバーに Docker がなければ自動インストール。

  3. ローカルとリモートでイメージレジストリにログイン。

  4. プロジェクトルートの Dockerfile を使ってイメージをビルド。

  5. イメージをレジストリにプッシュ。

  6. サーバーにイメージをプルさせる。

  7. kamal-proxy が 80/443 ポートで動作していることを確認。

  8. 新しいコンテナを起動。

  9. GET /up200 OK を返すのを待機。

  10. トラフィックを新しいコンテナに切り替え。

  11. 古いコンテナを停止し、不要なイメージと停止したコンテナをクリーンアップ。

ここで非常に重要なポイントが一つあります。**ヘルスチェックのデフォルトは GET /up です**。そのため、アプリケーションにはこのような軽量なヘルスチェックエンドポイントを用意することをお勧めします。そうしないと、新しいコンテナが起動しても Kamal がトラフィックを切り替えてくれない可能性があります。

その後のデプロイはずっとシンプル

初回の setup が成功した後は、通常は次のコマンドを実行するだけで更新できます:

bash
kamal deploy

ドキュメントでは、これをその後のデプロイコマンドとして明確に指定しています。「通常のリリースエントリ」と考えてください。イメージの再ビルド、プッシュ、プル、新コンテナの起動、ヘルスチェック、トラフィックの切り替え、古いコンテナの停止を行います。

したがって、使用感としては、Kamal の最も快適な点は、初回デプロイで少し準備をすれば、その後は安定して動作することです。

よく使う操作

入門段階では、以下のコマンドが最も実用的です:

初期化

bash
kamal init

ベースとなるデプロイファイルを生成します。

初回デプロイ

bash
kamal setup

サーバー、Docker、イメージ、プロキシ、アプリケーションを初めて一緒に立ち上げます。

その後のリリース

bash
kamal deploy

日常的に最もよく使うコマンドです。

マルチ環境デプロイ

後で stagingproduction を区別し始める場合、Kamal は -d で destination を指定できます。例:

bash
kamal deploy -d staging

公式ドキュメントによると、このとき Kamal は config/deploy.staging.yml を基本設定とマージして使用します。

この機能は非常に便利ですが、まだ入門段階であれば、存在を知っておくだけで十分で、すぐに使う必要はありません。

なぜ Rails と相性が良いのか

Rails 8 の新規プロジェクトには通常すでに Dockerfile が含まれており、Kamal のデプロイフローはまさに Dockerfile を中心に展開されます。さらに、Rails エコシステムはもともと Ruby gem のツールチェーンを自然に受け入れるため、Rails から Kamal に触れるのはほぼ自然な流れです。

私自身も、まず Rails プロジェクトでこの方法を見たからこそ、真剣に長期的に使えるデプロイソリューションとして Kamal を検討し始めました。

Next.js の入門ユースケース

最後に、私の日常に近い例を紹介します。Next.js プロジェクトを Kamal でデプロイする場合、通常は標準の Docker アプリケーションとして作成し、それを Kamal に任せてリリースします。

ステップ1:Next.js を standalone 出力にする

Next.js のドキュメントによると、output: 'standalone' を有効にすると、ビルド成果物として .next/standalone が生成され、デプロイと実行に必要な最小限のファイルと server.js が含まれます。これは Docker デプロイに非常に適しており、完全な開発環境をそのまま持ち込む必要がありません。

next.config.js には次のように記述できます:

js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',
}

module.exports = nextConfig

注意点として、Next.js のドキュメントでは、output: 'standalone' の実行方法は、生成された server.js を直接使う方が適切であり、next start を使い続けるべきではないとされています。

ステップ2:Dockerfile の準備

シンプルな Next.js の Dockerfile は次のようになります:

Dockerfile
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/static ./.next/static
EXPOSE 3000
CMD ["node", "server.js"]

ここでのポイントは Docker のテクニックそのものではなく、考え方です。**まず Next.js を標準の実行可能なコンテナにし、その後 Kamal にデプロイを任せる** ということです。

ステップ3:Kamal 設定の記述

例:

yaml
service: my-next-app
image: your-registry-user/my-next-app

servers:
  - 203.0.113.10

registry:
  username: your-registry-user
  password:
    - KAMAL_REGISTRY_PASSWORD

builder:
  arch: amd64

env:
  clear:
    PORT: 3000
    NODE_ENV: production

この設定のロジックは非常にシンプルです:

ステップ4:ヘルスチェックエンドポイントの追加

Kamal はデフォルトで GET /up をチェックするため、Next.js に最もシンプルなルートを追加します。例えば App Router の場合:

ts
export async function GET() {
  return Response.json({ ok: true })
}

これを例えば app/up/route.ts に配置すると、/up がシンプルな成功レスポンスを返すようになります。このエンドポイントはできるだけ軽量であることが望ましく、目的は Kamal に「コンテナがトラフィックを受け付け可能です」と伝えることだけです。

ステップ5:デプロイ

最後に、Kamal の標準フローに戻ります:

bash
kamal setup

その後の更新:

bash
kamal deploy

このフローが Next.js プロジェクトで安定して動作するなら、次のことがわかります。Kamal はアプリケーションが Rails かどうかは気にしません。本当に重視しているのは、**標準の Docker イメージを提供できるかどうか、そしてヘルスチェックが可能な Web サービスを用意できるかどうか** です。

今回はここまで

もしあなたも私のように、まず Rails 8 で Kamal に触れ、徐々にこの方法を Next.js 16 プロジェクトに移行しているなら、Kamal2 の位置づけは非常に理解しやすいと思います。それはプラットフォームではなく、セルフホストの Docker デプロイをより秩序立てて行うためのツールです。

入門段階では、以下のことを押さえておけば十分です:

これらがスムーズに動くようになってから、マルチ環境、accessories、フック、複雑なプロキシ設定などを学ぶ方が自然でしょう。

共有

共有

この記事を共有します。