
Excelで回っている社内承認フローを、そろそろWebアプリに移したい。
そう思いながらも「どのツールを選べばいいか分からない」「セルフホストの手間が読めない」という理由で後回しにしているケースは多いと思います。
ToolJetをDocker Composeでセルフホストして、入力→DB保存→承認ステータス管理という最小構成の申請フォームを組むまでの流れを実際に追います。
あわせてRetool・Appsmithとの比較軸を整理して、「ToolJetを選ぶかどうか」を自分の文脈で判断できる材料を提供します。
ToolJetを選ぶ前に整理しておきたいこと――RetoolとAppsmithとの比較
ToolJetは AGPLv3 のオープンソースプロジェクトです。
セルフホスト自体は無料で始められますが、監査ログ・SCIM・マルチ環境管理といったエンタープライズ機能は有償プランに閉じています。
この点を最初に把握しておかないと、後から「あの機能が使えない」と気づいて計画が狂います。
同じ領域のツールとしてRetoolとAppsmithがよく比較対象に挙がります。
三者の違いを「セルフホスト可否・ライセンス・価格帯・UIビルダーの使い勝手」という軸で整理すると、だいたい次のような像が見えてきます。
Retool はクローズドSaaS寄りの設計で、コネクタ数は三者の中で最多です。
SQL・REST・GraphQL・Firebase・Salesforceといった主要なものはほぼ揃っています。
一方でコストが重く、BusinessプランはBuilder1人あたり月50ドル、End-userは月15ドルという構成です。
Appsmith はApache 2.0ライセンスで、セルフホストしても商用利用に制限がありません。
Businessプランは月15ドル/ユーザーで、監査ログ・SSO・高度なアクセス制御が使えます。
UIビルダーの完成度は高く、コミュニティも活発です。
ToolJet はセルフホスト版のBusinessプランが月8ドル〜という価格帯で、三者の中でコストを抑えやすい選択肢です。
UIビルダーはドラッグ&ドロップで直感的に操作でき、80以上のデータソースに接続できます。
AGPLv3の含意には注意が必要で、改変して社内利用する分には問題ありませんが、SaaSとして外部提供する場合はソース開示義務が生じます。
「社内ツールをセルフホストで安く回したい・既存DBに管理画面を素早く被せたい」という文脈なら、ToolJetを選ぶ合理的な理由があります。
コネクタ数や完成度でRetoolに及ばない部分はありますが、その差を価格差が埋めてくれるかどうかが判断軸になります。
Docker ComposeでToolJetをセルフホストする
公式が提供しているdocker-compose.yamlを使うのが最短ルートです。
ゼロからDockerfileを書く必要はなく、設定ファイルを取得して環境変数を埋めれば動き始めます。
まず作業ディレクトリを作って公式の設定ファイルを取得します。
mkdir tooljet && cd tooljet
curl -LO https://raw.githubusercontent.com/ToolJet/ToolJet/main/deploy/docker/docker-compose.yaml
curl -LO https://raw.githubusercontent.com/ToolJet/ToolJet/main/deploy/docker/.env.example
cp .env.example .env
取得した.envを開いて、最低限これだけは設定します。
# アプリの署名・暗号化に使うキー。必ず変更する
SECRET_KEY_BASE=ここに64文字以上のランダム文字列を入れる
LOCKBOX_MASTER_KEY=ここに32バイトのランダム16進数を入れる
# ToolJetが外部からアクセスされるURL
TOOLJET_HOST=http://localhost
# 内蔵PostgreSQLのパスワード(デフォルトから変更推奨)
PG_PASS=変更してください
SECRET_KEY_BASEとLOCKBOX_MASTER_KEYの設定漏れは、起動はするけど暗号化まわりで後から問題が出る典型的なつまずきです。
面倒でも最初に設定しておきましょう。
環境変数を埋めたら起動します。
docker compose up -d
デフォルトはポート80番を使います。
すでにnginxや他のサービスが80番を使っている環境では起動に失敗するので、docker-compose.yamlのports設定を変更してください。
services:
tooljet:
ports:
- "8080:3000" # 左側のホスト側ポートを空いているものに変更
起動後にブラウザでlocalhostを開くと初回ログイン画面が表示されます。
ここで管理者アカウントを作成します。メールアドレスとパスワードを設定するだけで、特別な手順はありません。
Windows環境で試す場合はWSL2上で作業することを強く推奨します。
.envファイルの改行コードがCRLFになっていると環境変数の読み込みが壊れるので、WSL2ターミナル内で作業するかエディタでLFに変換してから保存してください。
本番環境に投入する前には、SSL終端の設定とデータのバックアップ戦略を別途検討する必要があります。
公式ドキュメントにDockerバックアップ用のシェルスクリプトが用意されているので、本番移行前に参照してください。
社内申請フォームを実際に組む――DataSource接続からステータス管理まで
ここからが本題です。
「入力→DB保存→承認ステータス更新」という最小構成のフローを、操作の流れに沿って追います。
まずPostgreSQL側でテーブルを用意します。
CREATE TABLE requests (
id SERIAL PRIMARY KEY,
applicant_name VARCHAR(100) NOT NULL,
title VARCHAR(200) NOT NULL,
description TEXT,
status VARCHAR(20) DEFAULT 'pending', -- pending / approved / rejected
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
ToolJetの管理画面を開いたら、左サイドバーのData SourcesからPostgreSQLを選択します。
ホスト・ポート・データベース名・ユーザー・パスワードを入力して「Test Connection」をクリック。
接続が確認できたら保存します。
セルフホスト環境で同一Dockerネットワーク内のPostgreSQLに接続する場合、ホスト名はlocalhostではなくDockerのサービス名(postgresなど)を指定する必要があります。
ここでlocalhostを入力してしまって繋がらない、というのはよくあるつまずきです。
DataSourceが繋がったら、アプリを新規作成してUIビルダーを開きます。
Formコンポーネントをキャンバスにドラッグして、中にText Input(申請者名・件名)とText Area(内容)を配置し、Submitボタンを設置します。
次にQueriesから「Add Query」を選択し、先ほど接続したPostgreSQLを選びます。
申請を登録するINSERTクエリを書きます。
INSERT INTO requests (applicant_name, title, description)
VALUES (
'{{components.textInput1.value}}',
'{{components.textInput2.value}}',
'{{components.textArea1.value}}'
)
二重波括弧の中はコンポーネントの値を参照するToolJetの記法です。
クエリを保存したら、FormのSubmitボタンの「On Click」イベントにこのクエリを紐付けます。
これで申請フォームの基本動作は完成です。
承認側の画面も同じ要領で作ります。
Tableコンポーネントを配置してSELECTクエリでrequestsテーブルの内容を引っ張り、行を選択したときに承認・却下ボタンが有効になるようにします。
それぞれのボタンに次のようなUPDATEクエリを紐付けます。
UPDATE requests
SET status = 'approved', updated_at = NOW()
WHERE id = {{components.table1.selectedRow.id}}
却下の場合はapprovedをrejectedに変えるだけです。
ここで便利なのが、JavaScriptでコンポーネントの表示を制御できる点です。
承認ボタンを承認者だけに表示したい場合、ボタンのVisibilityプロパティに次のような式を書けます。
{{globals.currentUser.email === 'approver@example.com'}}
実際の運用では特定のメールアドレスで判定するより、ToolJetのグループ機能でロールを管理する方がスマートです。
ただしグループ・RBACの細かい制御は有償プランの機能になるので、コミュニティ版ではこうしたJS式での簡易制御が現実的な選択肢になります。
「ノーコードツールはロジックが複雑になった瞬間に詰まる」というイメージを持っている人も多いと思いますが、ToolJetはコンポーネントのほぼすべてのプロパティにJavaScriptの式を書けます。
「ビジュアルビルダーで8割組んで、残りの2割をJSで補う」という使い方ができるのが、純粋なノーコードツールとの大きな違いです。
AIエージェント連携は今どこまで使えるか
ToolJetのAI関連機能は、現時点で大きく3つの層に分かれています。
1層目は ToolJet AI によるスキャフォールド生成です。
プロンプトを入力するとUIコンポーネント・クエリ・バインディングをまとめて生成してくれます。
「白紙のキャンバスから始めなくて済む出発点」として使うなら実用的ですが、生成されたものは手直しが前提で、そこからが本当の作業になります。
2層目は WorkflowのAgent Node です。
WebhookやCronをトリガーにして、AIモデルがツール呼び出しを計画・実行するマルチステップ処理を組めます。
メールを受信→内容を分類→DBに書き込む、といった自動化フローをコードなしで構成できます。
公式ドキュメントにはGmailからメールを取得して分類するAgent Nodeの例が載っており、実際に動く仕組みとして整備されています。
3層目は MCP(Model Context Protocol)サーバー経由の連携 です。
Claudeなどの外部AIアシスタントからToolJetを操作できる仕組みで、ユーザー管理・アプリ一覧取得・ロール変更といった操作をAIアシスタントに委譲できます。
正直なところ、主要なAI機能はエンタープライズプランに閉じています。
コミュニティ版で使えるのはビジュアルビルダーとデータ接続が中心です。
AI機能を目当てにToolJetを選ぶ場合は、プランと機能の対応を公式ドキュメントで確認してから判断してください。
実務で使い続けるときに直面すること
試作段階では気にならなかったことが、実運用に移ると徐々に見えてきます。
日本語のドキュメントはほぼありません。
公式ドキュメントは英語で、コミュニティフォーラムも英語が中心です。
Retoolに比べるとコミュニティの規模は小さく、エラーメッセージをそのまま検索しても情報が出てこないケースがあります。
トラブルシューティングはGitHubのIssuesやDiscussionsを掘ることになります。
アップデートが活発なのは良い面でもありますが、セルフホスト版を運用していると追従コストが発生します。
マイナーバージョンでもdocker-compose.yamlや環境変数の仕様が変わることがあるので、更新前に変更履歴を確認する習慣が必要です。
AGPLv3ライセンスの点も念頭に置いてください。
社内ツールとして改変・利用する分には問題ありません。
ただしToolJetをベースにしたサービスを外部に提供する場合は、改変したソースコードの開示義務が生じます。
SaaSとして展開する予定がある場合は、ライセンスの扱いを法務と確認しておくことをおすすめします。
向いているユースケースと向いていないユースケースを整理すると、次のようになります。
- 向いているケース: 既存のDBやAPIに管理画面を素早く被せたい / 社内限定ツールでライセンスコストを抑えたい / 承認フロー・データ閲覧・簡易ダッシュボードのような社内オペレーションツール
- 向いていないケース: 外部ユーザーに公開するプロダクト / 複雑なUIやアニメーションが必要なアプリ / モバイルファーストで設計したいアプリ / ToolJetをベースにSaaS展開を考えているケース(AGPLv3の制約)
「Excelで回っている承認フロー」の移行先としてToolJetは現実的に機能します。
DataSource接続→フォーム作成→クエリ紐付けという流れは、慣れれば半日もあれば動くものが作れます。
ただし「作れる」と「運用できる」は別の話で、日本語ドキュメントの薄さ・アップデート追従・エンタープライズ機能の有償化という壁は実運用で必ず顔を出します。
「まず動くものを作って社内で使い始める」という段階には十分使えるツールです。
その先のスケールアップをどう設計するかは、実際に使いながら判断していくのが現実的だと思います。
株式会社ホコサキは山口県宇部を拠点に、Web制作・業務システム開発・AI活用支援を手がけています。
ToolJetのようなローコードツールを使った社内システムの立ち上げや、既存フローのWeb化についてもご相談を受け付けています。
気になることがあれば お問い合わせページ からお気軽にどうぞ。

