kamal-coder について
kamal-coderは、Kamal 2のデプロイ設定と運用を支援するスキルです。コンテナ化したアプリをサーバーへ配置するチーム向けに、プロキシやシークレット、複数ロール、日常運用を扱います。
主な機能
- 01Kamal 2のデプロイ設定
- 02Webとジョブのロール設定
- 03プロキシ、SSL、ヘルスチェック
- 04シークレットと環境別設定
- 05デプロイ、ロールバック、デバッグ
- 06ビルダーとアクセサリーの設定
活用シーン
- 01本番またはステージング環境の構築
- 02サーバーでWebとジョブのコンテナを稼働
- 03SSLとヘルスチェックの設定
- 04ログ確認やリリースのロールバック
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ majesticlabs-dev/ majestic-marketplace --skill kamal-coderインストール後、Claude Code で/kamal-coderを入力して読み込まれたか確認します。
同梱ファイルreferences/docker-patterns.mdreferences/request-flow.md
詳細
Kamal 2 コーダー
サーバーには Docker、SSH アクセス、およびポート 22/80/443 の開放が必要です。Ansible または cloud-init でプロビジョニングしてください。
設定:config/deploy.yml
最小構成
service: myapp
image: myapp
servers:
web:
- 203.0.113.10
proxy:
ssl: true
host: myapp.com
registry:
username: username
password:
- KAMAL_REGISTRY_PASSWORD
env:
clear:
RAILS_ENV: production
RAILS_LOG_TO_STDOUT: "true"
secret:
- RAILS_MASTER_KEY
マルチロール構成(Web + ジョブワーカー)
service: myapp
image: myapp
servers:
web:
- 203.0.113.10
job:
hosts:
- 203.0.113.10
cmd: bin/jobs start
proxy:
ssl: true
host: myapp.com
registry:
username: username
password:
- KAMAL_REGISTRY_PASSWORD
env:
clear:
RAILS_ENV: production
SOLID_QUEUE_IN_PUMA: false
secret:
- RAILS_MASTER_KEY
ジョブワーカーに関する注意:
cmd: bin/jobs startは Solid Queue を別のコンテナで実行します- プロセス内キューを無効にするには、
SOLID_QUEUE_IN_PUMA: falseを設定します - ジョブロールにはプロキシがありません。HTTP トラフィックを処理するのは Web ロールのみです
ローカルレジストリを使用する場合
Docker Hub への依存、レート制限、外部コストを解消します。
registry:
server: localhost:5555
username: ignored
password:
- KAMAL_REGISTRY_PASSWORD
レジストリをアクセサリーとしてデプロイします。
accessories:
registry:
image: registry:2
host: 203.0.113.10
port: "5555:5000"
volumes:
- registry_data:/var/lib/registry
アクセサリーを使用する場合
accessories:
db:
image: postgres:16
host: 203.0.113.10
port: 5432
env:
clear:
POSTGRES_DB: myapp_production
secret:
- POSTGRES_PASSWORD
directories:
- data:/var/lib/postgresql/data
options:
shm-size: 256m
redis:
image: redis:7-alpine
host: 203.0.113.10
port: 6379
directories:
- data:/data
cmd: redis-server --appendonly yes
永続化のための Docker ボリューム
SQLite + ActiveStorage アプリでは、名前付きボリュームをマウントします。
servers:
web:
hosts:
- 203.0.113.10
volumes:
- myapp_storage:/rails/storage
labels:
docker-volume-backup.stop-during-backup: "true"
job:
hosts:
- 203.0.113.10
cmd: bin/jobs start
volumes:
- myapp_storage:/rails/storage
Web コンテナとジョブコンテナは、データベースへのアクセスに同じボリュームを共有します。
プロキシ設定(kamal-proxy)
Kamal 2 では Traefik ではなく kamal-proxy を使用します。SSL 終端、ルーティング、ダウンタイムなしのデプロイを処理します。
基本的な SSL
proxy:
ssl: true
host: myapp.com
Let's Encrypt 証明書が自動的にプロビジョニングされるため、証明書を手動で管理する必要はありません。
カスタムポート
proxy:
ssl: true
host: myapp.com
app_port: 3000
複数のホスト
proxy:
ssl: true
hosts:
- myapp.com
- www.myapp.com
ヘルスチェック
proxy:
ssl: true
host: myapp.com
healthcheck:
path: /up
interval: 3
timeout: 3
レスポンスタイムアウト
proxy:
ssl: true
host: myapp.com
response_timeout: 30
シークレット:.kamal/secrets
Kamal は .kamal/secrets(Git の追跡対象外)からシークレットを読み込みます。
1Password CLI を使用する場合
KAMAL_REGISTRY_PASSWORD=$(op read "op://Infrastructure/DockerHub/password")
RAILS_MASTER_KEY=$(op read "op://MyApp/production/master_key")
DATABASE_URL=$(op read "op://MyApp/production/database_url")
環境変数を使用する場合
KAMAL_REGISTRY_PASSWORD=$DOCKERHUB_TOKEN
RAILS_MASTER_KEY=$RAILS_MASTER_KEY
DATABASE_URL=$DATABASE_URL
複数の環境
# config/deploy.yml — base config
service: myapp
# config/deploy.staging.yml — overrides
service: myapp-staging
servers:
web:
- 203.0.113.20
proxy:
host: staging.myapp.com
# .kamal/secrets.staging
RAILS_MASTER_KEY=$(op read "op://MyApp/staging/master_key")
次のコマンドでデプロイします:kamal deploy -d staging
よく使うコマンド
初回デプロイ
# One-time: installs kamal-proxy, pushes image, deploys
kamal setup
# Subsequent: builds, pushes, rolling restart
kamal deploy
通常の操作
kamal deploy # Deploy latest
kamal deploy --version=abc123 # Deploy specific version
kamal deploy -d staging # Deploy to staging
kamal redeploy # Redeploy without building
ロールバック
kamal app containers # List available versions
kamal rollback <version> # Rollback to specific version
デバッグ
kamal app exec --interactive bash # Shell into container
kamal app logs -f # Tail logs
kamal app exec --interactive "bin/rails console" # Rails console
kamal app exec "bin/rails db:migrate" # Run migrations
アクセサリー
kamal accessory boot all # Start all accessories
kamal accessory reboot db # Restart specific accessory
kamal accessory exec db --interactive "psql -U postgres"
kamal accessory logs litestream # View accessory logs
ビルダー設定
ネイティブビルド
builder:
arch: amd64
マルチアーキテクチャ
builder:
multiarch: true
リモートビルダー
builder:
remote:
arch: amd64
host: ssh://builder@build-server
ビルド引数
builder:
args:
RUBY_VERSION: "3.3.0"
フック
デプロイ前
# .kamal/hooks/pre-deploy
#!/bin/sh
echo "Running pre-deploy checks..."
デプロイ後
# .kamal/hooks/post-deploy
#!/bin/sh
echo "Deploy complete: $(date)"
curl -s https://notify.example.com/deploy
プロビジョニングのワークフロー
Ansible + Kamal パイプライン
# 1. Ansible: Configure server
ansible-playbook -i hosts.ini playbook.yml
# 2. Kamal: Bootstrap and deploy
kamal setup
Ansible で設定する項目
kamal-ansible-manager に基づきます。
| タスク | 目的 |
|---|---|
| Docker のインストール | コンテナランタイム |
| fail2ban の設定 | SSH への侵入防止 |
| UFW のセットアップ | ファイアウォール(22、80、443) |
| NTP の有効化 | 時刻同期 |
| スワップの作成 | メモリ不足時の保護 |
| SSH の強化 | パスワード認証と root ログインを無効化 |
| 無人アップグレード | セキュリティパッチの自動適用 |
Litestream バックアップアクセサリー
SQLite アプリでは、Litestream をアクセサリーとして追加します(完全な設定は litestream-coder を参照してください)。
accessories:
litestream:
image: litestream/litestream:0.3
host: 203.0.113.10
cmd: replicate
volumes:
- myapp_storage:/rails/storage:ro
files:
- config/litestream.yml:/etc/litestream.yml
env:
secret:
- LITESTREAM_ACCESS_KEY_ID
- LITESTREAM_SECRET_ACCESS_KEY
ストレージは読み取り専用(:ro)でマウントしてください。Litestream が WAL ファイルを読み取るだけだからです。
ディレクトリ構成
myapp/
├── config/
│ ├── deploy.yml # Main Kamal config
│ └── deploy.staging.yml # Staging overrides
├── .kamal/
│ ├── secrets # Production secrets (git-ignored)
│ ├── secrets.staging # Staging secrets (git-ignored)
│ └── hooks/
│ ├── pre-deploy
│ └── post-deploy
├── Dockerfile # Application container
└── docker-entrypoint.sh # Entrypoint script
トラブルシューティング
| 問題 | 原因 | 対処方法 |
|---|---|---|
| 接続が拒否される | Docker が実行されていない | kamal setup を実行するか、Docker サービスを確認します |
| 権限が拒否される | SSH キーが認証されていない | サーバーの authorized_keys を確認します |
| ヘルスチェックに失敗する | アプリが起動していない | kamal app logs を確認します |
| レジストリ認証に失敗する | 認証情報が間違っている | .kamal/secrets を確認します |
| 502 Bad Gateway | コンテナが正常でない | ヘルスチェックのタイムアウトを延長します |
| SSL 証明書が発行されない | DNS がサーバーを指していない | DNS の A レコードを確認します |
| デプロイ後にアセットが 404 になる | ボリュームがマウントされていない | deploy.yml の volumes: を確認します |
参考資料
- references/request-flow.md — リクエストアーキテクチャと Cloudflare の統合
- references/docker-patterns.md — 本番環境向け Dockerfile、エントリーポイント、ボリュームのパターン