0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

管理ポータルを触らずにクラウド環境を構築(IBM Cloud CLI, IBM Bob)

0
Posted at

はじめに

IBM Bob で AI 駆動開発したマルチプレイゲームを、Bob 自身に IBM Cloud CLI を使ってデプロイさせた体験記です。ポータルを操作せず、Bob が生成したデプロイ計画書に沿って CLI だけで完結させました。

image.png

アプリ概要

宇宙対抗バトル(team-buttle) ─ 最大 30 人が同時参加するA/Bチーム対抗リアルタイム WebSocket ゲーム。

  • フロントエンド: p5.js(チーム対抗シューティングゲーム)
  • バックエンド: Node.js + Express + ws(WebSocket サーバー)
  • 状態管理: サーバーメモリのみ(DB なし)

ゲーム画面

二層構成 → IBM Cloud リソースマッピング

アプリは「フロントエンド / バックエンド」の2つの役割で構成されており、それぞれ IBM Cloud の別サービスに対応させます。

役割 技術スタック 移植前(IaaS) IBM Cloud(サーバレス)
フロントエンド(HTML/JS/CSS) p5.js + 静的ファイル nginx リバースプロキシ経由 ICOS 静的ウェブホスティング
バックエンド(WebSocket サーバー) Node.js + ws + Express pm2 on Linux VM IBM Code Engine(コンテナ)
コンテナイメージ置き場 Docker イメージ (なし) IBM Container Registry(ICR)

3 サービスを使うため、ポータルで手作業するだけで何画面も操作が必要になります。これを CLI で一括自動化するのが今回の肝です。


移植方式の相談 ─ なぜ CLI にしたか

まず Bob に「API 経由で Code Engine にデプロイしたい」と伝えたところ、3 つの方式を提案されました。

  1. IBM Cloud API をラップした MCP Server を自作
  2. IBM Cloud CLI でコード化(今回採用)
  3. Terraform を MCP で操作する

どれにするか迷いましたが、比較すると CLI が最もリスクが低いと判断しました。

比較軸 MCP Server 自作 ibmcloud CLI コード化
実装コスト 高い(MCPサーバーのスキャフォールド+IBM Cloud SDK実装) 低い(CLIコマンドをスクリプト化するだけ)
信頼性・安定性 IBM Cloud SDK の変更に追従が必要 CLI は後方互換性が高く安定
Bob との統合 ネイティブ(ツールとして直接呼べる) シェル実行経由(execute_command)
デバッグのしやすさ 難しい(MCPレイヤー+API層の2段構え) 簡単(CLIコマンドをターミナルで直接試せる)
認証管理 IAM APIキーをMCPサーバー側で管理 ibmcloud login 済みセッションを再利用できる
エラーメッセージ 自前でパース・整形が必要 CLI が人間可読なメッセージを返してくれる
対応サービスの幅 実装した分だけ ibmcloud CLI プラグインが対応する全サービス
オフライン開発 SDK変更でテスト環境が壊れうる --dry-run--help でオフライン確認可
再利用性 高い(他プロジェクトにも適用可) スクリプトはプロジェクト依存になりがち
将来IBM公式MCPが出たとき 作り直し or 競合が発生 CLIスクリプトはそのまま残せる

結論: 今回は CLI を選択。将来 IBM 公式 MCP が整備されたら移行する余地も残しつつ、まず動くものを作る方針に決定。


Bob のドキュメント生成力

Bob の最大の特長はコードだけでなくドキュメントも生成できることです。今回のプロジェクトでは以下のドキュメントをすべて Bob が生成しました。

要件定義.md          ← 箇条書きの要件をBobに渡すと整形された要件定義書に
設計書.md            ← WebSocketプロトコル・座標系・難易度表・既知不具合まで全網羅
操作手順書(ゲーム).md ← 管理者・プレイヤー両視点の操作フロー
Bobデプロイ計画.md   ← 6フェーズのCLI手順・コスト見積もり・運用注意事項

Bob がデプロイ計画書を生成した流れ(7章構成):

  1. アーキテクチャ概要
  2. 前提条件・依存関係
  3. 設計上の重要課題(WebSocket URL の構成変更など)
  4. デプロイ全体フロー(フェーズ1〜6)
  5. 環境変数一覧
  6. コスト見積もり
  7. 運用上の注意事項

ポイントは「Bob が計画書を作り、その計画書通りに Bob が CLI を実行する」という一気通貫のワークフローです。

なお、フェーズ1~6は次の通り:
(1) IBM Cloud 環境準備
(2) コンテナイメージのビルドと ICR への push
(3) Code Engine アプリのデプロイ
(4) ICOS バケット作成と静的ファイルアップロード
(5) ICOS の静的ウェブサイトホスティング設定
(6) 動作確認

image.png


IBM Cloud CLI の準備

CLI 本体のインストール

IBM Cloud CLI の公式インストーラーを使います。
https://cloud.ibm.com/docs/cli?topic=cli-install-ibmcloud-cli

必要なプラグインのインストール

3 つのプラグインが必要です。

ibmcloud plugin install code-engine
ibmcloud plugin install container-registry
ibmcloud plugin install cloud-object-storage

その他の前提ツール

このアプリでは実行環境をつくるため Docker と Node.js もインストールが必要です

ツール 用途 確認コマンド
Docker Desktop コンテナイメージのビルド・プッシュ docker version
Node.js 18 以上 ローカル動作確認用 node --version

CLI の初期設定 ─ Bob への最初の伝え方

.env ファイルに API キーを書く

API キーをコードにハードコードしない代わりに、.env ファイルに記載します。

IBM_CLOUD_API_KEY=<YOUR_API_KEY>
IBM_CLOUD_REGION=jp-tok
IBM_CLOUD_RESOURCE_GROUP=Default

.gitignore への追加も必須:

.env

Bob へ伝える際の実際のやり取り

タスク実行前に、Bob から質問が来ました。

Bob の質問:
「IBM Cloud のリソース状況について、Code Engine プロジェクトと ICOS バケットは既に作成済みですか?また、使用予定の IBM Cloud リージョンを教えてください(例:jp-tok, us-south など)」

私の回答:
「[.env] ファイルに記載あるので参照して」

Bob の応答:
「完璧です。必要な情報が揃いました。計画書を作成します。」

コツ: .env ファイルの存在を Bob に伝えるだけで、Bob が自律的に必要な情報を収集します。API キーをチャットに貼り付ける必要は一切ありません。

ログイン〜ターゲット設定

# API キーをシェル変数経由で渡す(コマンド履歴に残らない)
ibmcloud login --apikey "$(grep IBM_CLOUD_API_KEY .env | cut -d= -f2)" -r jp-tok

# リソースグループの設定
ibmcloud target -g default

# プラグインの確認
ibmcloud plugin list | Select-String "code-engine|container-registry|cloud-object-storage"

セキュリティのポイント: $(grep ...) でシェル変数経由で渡すことで、API キーがコマンド履歴(~/.bash_history 等)に残りません。


Bob に IBM Cloud CLI デプロイをさせる(全工程)

Bob が生成した Bobデプロイ計画.md のフェーズに沿って実行します。

作業中の4パターン

実際の作業では、Bob は以下のパターンで進めます。

  • 問題に遭遇 → Bob が選択肢を提示し、人間が選ぶ
  • フェーズ毎に確認 → 次フェーズへ進む前に人間が OK を出す
  • 自動実行に失敗 → Bob が別の方法で試行する
  • 手作業が必要な作業 → Bob が具体的な指示を出す

フェーズ2: コンテナイメージをビルドして ICR にプッシュ

バックエンドを Docker イメージ化し、IBM Container Registry に登録します。

# ICR にログイン
ibmcloud cr login
ibmcloud cr region-set jp-tok

# 名前空間の作成
ibmcloud cr namespace-add team-buttle-ns

# イメージのビルドとプッシュ
docker build -t jp.icr.io/team-buttle-ns/multiplay-game:latest .
docker push jp.icr.io/team-buttle-ns/multiplay-game:latest

# プッシュ確認
ibmcloud cr image-list --restrict team-buttle-ns

Dockerfile(マルチステージビルド):

# ---- build stage ----
FROM node:18-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev

# ---- runtime stage ----
FROM node:18-alpine
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY server/ ./server/
COPY public/ ./public/
COPY package.json ./

ENV PORT=5011
ENV HOST=0.0.0.0
ENV NODE_ENV=production
ENV BASE_PATH=/

EXPOSE 5011
CMD ["node", "server/multi-play-server.js"]

HOST=0.0.0.0 の理由: Code Engine のコンテナは外部からアクセスを受けるため、127.0.0.1 ではなく 0.0.0.0 でリッスンする必要があります。


フェーズ3: Code Engine にアプリをデプロイ

# プロジェクトの作成と選択
ibmcloud ce project create --name multiplay-game-project
ibmcloud ce project select --name multiplay-game-project

# ICR へのアクセス権設定(Image Pull Secret)
ibmcloud ce secret create-registry \
  --name icr-secret \
  --server jp.icr.io \
  --username iamapikey \
  --password "$(grep IBM_CLOUD_API_KEY .env | cut -d= -f2)"

# アプリケーションの作成
ibmcloud ce application create \
  --name multiplay-game \
  --image jp.icr.io/team-buttle-ns/multiplay-game:latest \
  --registry-secret icr-secret \
  --port 5011 \
  --cpu 0.25 \
  --memory 0.5G \
  --scale-min-instances 1 \
  --scale-max-instances 1 \
  --env PORT=5011 \
  --env HOST=0.0.0.0 \
  --env NODE_ENV=production \
  --env BASE_PATH=/

# デプロイ後のURL確認
ibmcloud ce application get --name multiplay-game --output url

# ログ確認
ibmcloud ce application logs --name multiplay-game --follow

--scale-min-instances 1 の理由: WebSocket は常時接続が必要なため、Code Engine のデフォルト動作(トラフィックがないとインスタンスを 0 にスケールダウン)を防ぎます。
--scale-max-instances 1 の理由: ゲーム状態がサーバーメモリ上にあるため、複数インスタンスに分散すると状態の整合性が取れなくなります。

正常起動ログ:

team-buttle server listening on 0.0.0.0:5011, base path /

フェーズ4: フロントエンドを ICOS にアップロード

フロントエンドの静的ファイル(HTML/JS/CSS/MP3)を Cloud Object Storage に配置します。

# COS サービスインスタンスの作成
ibmcloud resource service-instance-create \
  multiplay-game-cos \
  cloud-object-storage \
  lite \
  global

# CRN の設定(COS CLI がどのインスタンスを操作するか指定)
ibmcloud cos config crn --crn "crn:v1:bluemix:public:cloud-object-storage:global::a/..."

# エンドポイント設定
ibmcloud cos config endpoint-url \
  --url https://s3.jp-tok.cloud-object-storage.appdomain.cloud

# バケットの作成
ibmcloud cos bucket-create \
  --bucket multiplay-*** \
  --region jp-tok \
  --ibm-service-instance-id "..."

静的ファイルのアップロード(PowerShell・日本語ファイル名対応):

$bucket = "multiplay-***"

Get-ChildItem -Path ./public -Recurse -File | ForEach-Object {
    $relativePath = $_.FullName.Substring(
        (Resolve-Path ./public).Path.Length + 1
    ).Replace('\', '/')

    $contentType = switch ($_.Extension) {
        ".html" { "text/html; charset=utf-8" }
        ".js"   { "application/javascript; charset=utf-8" }
        ".css"  { "text/css; charset=utf-8" }
        ".mp3"  { "audio/mpeg" }
        ".md"   { "text/markdown; charset=utf-8" }
        default { "application/octet-stream" }
    }

    Write-Host "Uploading: $relativePath"
    ibmcloud cos object-put `
        --bucket $bucket `
        --key $relativePath `
        --body $_.FullName `
        --content-type $contentType
}

このゲームは効果音に日本語ファイル名(例: カウントダウン電子音.mp3)を使っています。ibmcloud cos object-put は UTF-8 ファイル名をそのままオブジェクトキーとして扱えるため、リネーム不要です。


フェーズ5: ICOS を静的ウェブホスティングとして公開

# パブリック読み取りを許可
ibmcloud cos bucket-policy-put \
  --bucket multiplay-*** \
  --body '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::multiplay-***/*"]
    }]
  }'

# 静的ウェブサイトホスティングの有効化
ibmcloud cos bucket-website-put \
  --bucket multiplay-*** \
  --website-configuration '{
    "IndexDocument": { "Suffix": "multi-play.html" },
    "ErrorDocument": { "Key": "multi-play.html" }
  }'

アクセス URL:

# プレイヤー画面
http://multiplay-***.s3-website.jp-tok.cloud-object-storage.appdomain.cloud/multi-play.html

# 管理者画面
http://multiplay-***.s3-website.jp-tok.cloud-object-storage.appdomain.cloud/multi-play-admin.html

フェーズ6: 動作確認

# wscat で WebSocket 疎通確認
npx wscat -c wss://multiplay***.jp-tok.codeengine.appdomain.cloud/ws/player
# 接続後 25 秒でサーバーからping が届けば正常(ハートビート確認)

# ログ監視
ibmcloud ce application logs --name multiplay-game --follow

ブラウザ確認チェックリスト:

  • メイン アプリ稼働:ICOS の URL でプレイヤー画面が開く
  • 管理用 アプリ稼働:ICOS の URL で管理者画面が開く
  • 管理者画面で「募集開始」が押せる
  • プレイヤー画面でニックネームを入力して「申し込む」が成功する
  • チーム分け → ゲーム開始 → スコアが動く

セキュアになっているか

観点 対策
API キーをコードに書かない .env ファイルに記載し、Bob は .env を参照するよう指示
API キーを git にコミットしない .gitignore.env を追加
API キーをコマンド履歴に残さない $(grep IBM_CLOUD_API_KEY .env | cut -d= -f2) でシェル変数経由で渡す
ICR へのアクセス制御 Image Pull Secret(IAM API キーベースの認証)を Code Engine に登録
Bob がハードコードしていないか 生成されたコマンド・Dockerfile を確認 → .env 参照のみ、ベタ書きなし

実行結果

各フェーズの正常出力サンプル

フェーズ2: ICR イメージ確認

$ ibmcloud cr image-list --restrict team-buttle-ns
Repository                                           Tag      Digest    ...
jp.icr.io/team-buttle-ns/multiplay-game              latest   sha256:...

フェーズ3: アプリ起動ログ

$ ibmcloud ce application logs --name multiplay-game --follow
team-buttle server listening on 0.0.0.0:5011, base path /

フェーズ3: URL 確認

$ ibmcloud ce application get --name multiplay-game --output url
https://multiplay***.jp-tok.codeengine.appdomain.cloud

最終アクセス URL

用途 URL
プレイヤー画面(ICOS) http://multiplay-***.s3-website.jp-tok.cloud-object-storage.appdomain.cloud/play-***.html
管理者画面(ICOS) http://multiplay-***.s3-website.jp-tok.cloud-object-storage.appdomain.cloud/admin-***.html
WebSocket(Code Engine) wss://multiplay-***.jp-tok.codeengine.appdomain.cloud

IBM Cloud にリソースが出来ました!

image.png


コスト最適化

課金しているのは Code Engine アプリのみです。

リソース スペック 月額概算
Code Engine Application 0.25vCPU / 0.5GB × 最小1インスタンス常時稼働 ~$5–10 USD
IBM Container Registry 0.5GB 以下(lite 無料枠) $0
Cloud Object Storage 25GB 以下(lite 無料枠) $0

デプロイ後の節約術: 使わない期間は以下の手順で無料枠に収められます。

# ICOS のパブリックアクセス権を削除(フロントエンドを非公開に)
ibmcloud cos bucket-policy-delete --bucket multiplay-game-***

# Code Engine アプリを停止(インスタンスを 0 にスケールダウン)
ibmcloud ce application update --name multiplay-game --scale-min-instances 0

まとめ

  • Bob と CLI を組み合わせて、AI駆動アプリ開発からクラウドデプロイまでの流れがとっても時短
  • ポータルを操作せず、Bob が CLI だけでデプロイ完了(クラウドの学習コスト抑制)
  • 再現性の向上には Terraform による IaC が理想だが、繰り返しが不要なクラウド構築であればCLI でクラウド操作することを設計書で指示する手法は AI 時代に十分効果あり

本記事は、自分で執筆した「発表原稿」に対して IBM Bob が査読したものです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?