はじめに
本記事では、IBM Bobを用いてNode-REDをIBM Cloud Code Engine上に構築しました。
結果として、アプリのコードを書く必要はありませんでしたが、
- 試行錯誤はそれなりに必要
- プロンプトの精度が非常に重要
という知見が得られました。
IBM BobでIBM Cloud Code Engine上で稼働するNode-REDの構築をどこまで簡単にできる?
AIエージェントに対して自然言語で要件を伝えるだけでアプリケーションを生成する、いわゆる「AI駆動開発」が注目されています。IBM Bobは自然言語からアプリケーションやインフラ構成を生成できるAIエージェントです。
本記事では、IBM Bob」を使い、IBM Cloud上で稼働するNode-REDアプリを開発し、以下のような要求をそのまま渡してみました:
基本的な考え方
- Node-REDをローカルでもIBM Cloud Code Engine上でも稼働させる
- Code Engineはステートレスな実行環境であるため、フローの永続化先としてObject Storageを利用する
- 永続化の際の保存先はローカルファイル・システムもしくはIBM Cloud Object Storage(COS)とする
IBM Bobは仕様駆動開発に近いアプローチでビジネス要件やシステム要件をプロンプトとして与えると、それを解釈して実装に落とすのが得意なので、その実力を見ていきましょう。従来は上のような要件を満たすためにはJavaScriptのコードを書かないと実現できなかったので、ちょうどよいサンプルかと思います。基本的にコードは書かず、自然言語でプロンプトを与え、応答として得た結果をそのまま実施していきます。アプリケーションコード・構成・デプロイ手順あたりは自動生成してくれますが、デプロイについてはコマンドを実行しないといけない部分があるので、一部妥協しました。
本記事では、その一連の流れを紹介します。またBobが作成したファイルは github に一式アップロードしたので、ご興味ある方はそちらもご覧ください。README.mdにかかれている手順を実施すれば、この記事に記載したもろもろの対応を行うことなくそのまま実行できるはずです。
※ 本記事のAPIキーやパスワードはサンプルであり、実際の運用では適切に秘匿・管理してください。
あらかじめ用意するもの
- Podman 4.0以降
- Node.js 20以降 (パスワード生成ツール用)
- IBM Cloudアカウント (クレジットカード払いをはじめとする有料のサービスを利用できるもの)
- IBM Cloud Object Storage の「サービス・インスタンス」と「バケット」
- IBM Cloud Object Storage に書き込み権限を有する「サービスID」とその「API KEY」
- IBM Cloud Container Registryの「名前空間」
- IBM Cloud CLIと関連するプラグイン
IBM Cloudに関連する部分はインスタンスから名前空間の作成までは簡単に手順だけ以下のセクションにまとめました。適宜ご参照ください。
Object Storageのインスタンスとバケットの作成
- IBM Cloud (https://cloud.ibm.com) にログイン
- 既存のインスタンスを使用する場合にはリソースリスト (https://cloud.ibm.com/resources) からインスタンスの名前をクリック(手順5に進む)
- 新規のインスタンスを作成する場合には、Object Storageのカタログ (https://cloud.ibm.com/objectstorage/create) にアクセス
- Standard プラン を選択、サービス名にインスタンス名、リソース・グループはインスタンスを作成したいものをリストから選択し、「作成」をクリック
- 作成したObject Storageのインスタンスが表示されるので「バケットの作成」をクリック
- カスタム・バケットの作成の「作成」をクリック
- 固有のバケット名はデフォルトでユニーク値が設定されますが、任意の値を指定したい場合置き換えます。いずれのケースもバケットの名称を控えます
- 回復力は「Regional」、ロケーションは「日本-東京 (jp-tok)」、ストレージ・クラスは「Smart Tier」として「バケットの作成」をクリック
Object Storage用のサービスIDとAPI KEYの作成
- バケットを作成したサービスインスタンスをリソースリスト (https://cloud.ibm.com/resources) から選択し、インスタンスの名前をクリック
- 右上にある「詳細」をクリック

3. CRNの文字列(crnではじまり::で終わる文字列全体)を控えます。終わったら右上の「×」をクリック
Container Registry 名前空間の作成
- Container Registryの名前空間のページ (https://cloud.ibm.com/containers/registry/namespaces) にアクセス
- ロケーションは「東京」を選択
- 「作成」をクリック
- 適切なリソース・グループを選択し、「名前」を指定して「作成」 をクリック
IBM Cloud CLIと関連するプラグインのインストール
- IBM Cloud CLIのリリース版 (https://github.com/IBM-Cloud/ibm-cloud-cli-release/releases) から環境にあったものをダウンロードし、インストール
- ターミナル/コマンドプロンプトなどから以下のコマンドを実行しプラグインをインストール
% ibmcloud plugin install code-engine
% ibmcloud plugin install container-registry
- 導入したプラグインを確認
% ibmcloud plugin list
IBM Bob IDEでの操作
- IBM Bobを起動します。ログインを求められる場合にはログインします。
- モードは「Plan」モードに設定
- 以下のプロンプトを与えました
私はアプリケーションの開発エンジニアです。IBM Cloud Code Engine上でNode-REDのアプリケーションを稼働したいです。
Nodeの構成情報はIBM Cloud Object Storageに永続的なデータとして保管したいです。
Node.jsのベースイメージはRed Hat UBIのものを利用してください。RHEL 9ベースでNode.js バージョン20のものを選択します。
ローカル環境で稼働するためのリソース一式を準備してください。ローカル環境はMacです。
ローカル環境で使用するコマンドはDockerではなくPodmanを使用するようにしてください。
Node-REDのユーザーIDを「nodeuser」, パスワードを「nodepwd」としてください。パスワードは初期値で後から変えられるよう手順を整備してください。
Bobはこのプロンプトから環境を作るためのタスクを整理して、作成する手続きを定義します。
To Doリストに従いBobはここから多くのファイルを生成します。アクションの承認はBobの設定次第で求められる範囲や回数が異なるので、適宜承認します。
一通りの作成が終わると文書で作業結果を表示し、次に実施すべきアクションを示してくれます。
これに従い操作を進めます。最初に出来上がったものがそのまま稼働することは稀なのですが、とりあえず、動かしてみます。
Podman用の実行スクリプトの中でエラーになりました。
アプリのビルドはうまくいきましたが、実行は以下のエラーを得ました。
% podman logs -f node-red-app
IBM Cloud Object Storage client initialized
User directory exists: /opt/app-root/src/.node-red
Syncing flows from IBM Cloud Object Storage...
Downloading flows from COS: your-bucket-name-here/flows.json
Error downloading flows from COS: Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1
Downloading credentials from COS: your-bucket-name-here/flows_cred.json
IBM Cloud Object Storageの設定が不完全な状態でも、Node-REDがローカルストレージで動作するように修正され、COS設定がない場合はエラーではなく警告として扱い、ローカルストレージのみで動作するように修正されました。
修正された際に表示されるビルド、実行のコマンドを実行しますが、いくつかのエラーに直面し、実際に稼働するまで試行錯誤を繰り返します。これは裏を返せば、「プロンプトが設計書に相当する」ことを意味しており、AI駆動開発における重要なポイントだと感じました。
以下のようなエラーが発生し、その都度Bobが修正を行いました。
- 静的コンテンツディレクトリが存在しないため、Node-REDの起動時にエラーが発生した
- 環境変数 NODE_RED_PASSWORD_HASH が正しく設定されていなかったため再設定した
- 設定ファイルでpasswordフィールドを使用していたが、Node-REDではbcryptハッシュをそのままpasswordに指定する必要があったため修正した
- .env.exampleのパスワードハッシュが無効だった。新しい正しいハッシュで更新した
- Node-RED内部の通信でWebSocketの通信が実施できず、CORSの設定が必要だった
- WebSocket接続の問題が続き、Node-REDのバージョンとの互換性の問題を疑い、認証を一時的に無効化して、基本的な動作を確認した
- WebSocket接続の問題が続き、Node-REDの公式ドキュメントに従って、start.jsを完全に書き直した
- WebSocketの問題が解決後に認証機能を有効化したがパスワードの変更後の手続きが正しく機能しなかったので修正した
これらを修正したのち、Node-REDがようやく稼働するようになりました。
ログイン画面でユーザー/パスワードを入力して、フローを作成します。

デプロイするとローカル環境では一時的な領域にflow.jsonが保存されているので、ファイルシステム上に永続的なデータとして格納できるようにします。以下のコマンドで backupフォルダ下にflows.jsonファイルがコピーされます。
% podman cp node-red-app:/opt/app-root/src/.node-red/flows.json ./backup/
念のため ./backup/flows.json ファイルの内容を確認してみますが、フローのデータを格納したjsonが格納されていました。
フローのデータ
[
{
"id": "17598868010e914f",
"type": "tab",
"label": "フロー 1",
"disabled": false,
"info": "",
"env": []
},
{
"id": "90072726b8e06473",
"type": "inject",
"z": "17598868010e914f",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 180,
"y": 80,
"wires": [
[
"b408778f8486b58c"
]
]
},
{
"id": "b408778f8486b58c",
"type": "debug",
"z": "17598868010e914f",
"name": "debug 1",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 420,
"y": 100,
"wires": []
}
]%
ここまででローカル環境での稼働確認は終わりです。
IBM Cloud Code Engine上で稼働する
ローカル環境では稼働できるようになったので、これをIBM Cloud Code Engine上で稼働していきます。
docs/DEPLOY_TO_CODE_ENGINE.md にコマンドが列挙されていたのですが、それを一つずつ実行したくないので、簡単に実施できるよう、Bobにshellファイルを作ってもらいました。
docs/DEPLOY_TO_CODE_ENGINE.md の内容を簡単に実施できるようにshellファイルを作ってください
デプロイ用の deploy-to-code-engine.sh が作られたので実行してみます。
あらかじめIBM Cloud CLIでログインするのと、Container Registryにログインしておきます。その後に作成されたシェルを実行します。
% ibmcloud login
% ibmcloud cr login
%
% ./deploy-to-code-engine.sh
今回もローカルでの稼働と同じようにエラーが発生したので、その都度エラーメッセージをBobに与えて修正しました。
- Code Engineアプリの一時ストレージのサイズがサービスで許容する最大サイズを超えた指定になっていたため、適正なサイズに修正した
- Container Registryにアクセスするためのシークレット情報が不足していたため、デプロイスクリプトを修正した
- Object Storageにフローの情報が保存されていなかったので、COS関連の環境変数やCode Engineのシークレットを追加して、フローが保存されるよう修正した
最終的に deploy-to-code-engine.sh 実行時のパラメータの値としては以下のような値をセットしました。入力値の参考になるようなるべくそのままの形で
API KeyとNode-REDのパスワードは実際の値ではないものに置き換えてあります。API Keyのほうは実際の文字列に似せた文字列を示しています。
==========================================
デプロイ設定
==========================================
Container Registry名前空間を入力してください: icr-japan-tok
イメージタグを入力してください [latest]: latest
リージョンを入力してください [jp-tok]: jp-tok
Code Engineプロジェクト名を入力してください [node-red-project]: ce-project-japan-tok
アプリケーション名を入力してください [node-red-app]: node-red-app-cos-pv
ℹ IBM Cloud Object Storage設定
COS Endpoint: s3.jp-tok.cloud-object-storage.appdomain.cloud
COS API Key: 5yfx4PtegKpJhB0-giASzBOFG2tCTa_LSU6Stfrm70ck
COS Instance ID: crn:v1:bluemix:public:cloud-object-storage:global:a/27dc483dc1f14d2f821e8b3a4193ad13:5c4be884-0921-4218-a565-22c54424b39b::
COS Bucket Name: bucket-49x0uz9t5p8uplx
ℹ Node-RED認証設定
ユーザー名 [nodeuser]: nodeuser
パスワードハッシュを生成しますか? (y/n):
> y
ℹ パスワードを入力してください:
> node-red-code-engine@1.0.0 generate-password
> node scripts/generate-password.js
=== Node-RED パスワードハッシュ生成ツール ===
新しいパスワードを入力してください: ********
生成されたパスワードハッシュ:
$2a$08$YWs/MelebwUte3MY.qdvWO.cDkcRZ.IegKipukHpbJF8clwykzkmq
使用方法:
1. .envファイルを開く
2. NODE_RED_PASSWORD_HASH の値を上記のハッシュに置き換える
3. コンテナを再起動する
例:
NODE_RED_PASSWORD_HASH="$2a$08$YWs/MelebwUte3MY.qdvWO.cDkcRZ.IegKipukHpbJF8clwykzkmq"
npm notice
npm notice New minor version of npm available! 11.13.0 -> 11.17.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.17.0
npm notice To update run: npm install -g npm@11.17.0
npm notice
生成されたハッシュを入力してください: $2a$08$YWs/MelebwUte3MY.qdvWO.cDkcRZ.IegKipukHpbJF8clwykzkmq
Node-REDにアクセスすると以下のようなログイン画面が表示されるので、指定したユーザー名とパスワードでログインします。
そしてフローを編集してデプロイします。
フローデータは5分おきにObject Storageに保存されています。5分待った後にCloud Object Storageのバケットにあるflows.jsonファイルを確かめてみましょう。
// 定期的な同期(5分ごと)
setInterval(async () => {
console.log('🔄 Auto-syncing to IBM Cloud Object Storage...');
await cosClient.syncToCloud(settings.userDir);
}, 5 * 60 * 1000);
flows.jsonに含まれるフローのデータ
[
{
"id": "fd629b62805f76a4",
"type": "tab",
"label": "フロー 1",
"disabled": false,
"info": "",
"env": []
},
{
"id": "e428f6e0668581a2",
"type": "inject",
"z": "fd629b62805f76a4",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 220,
"y": 100,
"wires": [
[
"25854292d48f1b47"
]
]
},
{
"id": "962bb2318b6e3550",
"type": "debug",
"z": "fd629b62805f76a4",
"name": "debug 1",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 660,
"y": 140,
"wires": []
},
{
"id": "25854292d48f1b47",
"type": "function",
"z": "fd629b62805f76a4",
"name": "function 1",
"func": "\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 460,
"y": 120,
"wires": [
[
"962bb2318b6e3550"
]
]
}
]
このような形でスクラッチからコードを書くことなくNode-REDをデプロイできました。
Bob頑張りました!
まとめ
IBM Bobに自然言語で要件を渡すだけで、
- アプリ設計
- インフラ構成
- 実装コード
- デプロイ手順
まで生成されることが確認できました。アプリのコードは1行も書きませんでした。
一方で少し試行錯誤しないといけない部分があり、その手当てがうまくいかなかったケースもありました。WebSocket周りや認証といった実行環境依存の問題で、このあたりはAI単体では完全には解決しきれない領域だと感じました。
修正にかかるBobcoinの消費が大きくなっているので、必要とするサービスの利用料金も大きくなります。今回の作業では約 13.3 Bobcoinを使用しました。
今後は機能を実現する還元でもコストを「コードを書くこと」よりもプロンプトに含める「要件や仕様をどう書くか」が重要になっていきそうです。アイデアを形にするうえで、いつどのタイミングでどの程度具体的なプロンプトを与えるのかはエンジニアの力量が問われるところなのかもしれないと感じました。







