Dify でチャットボットや RAG を作り、n8n で外部サービスとの連携を自動化する、という組み合わせはよく使われます。2台の VPS を借りるより1台にまとめたほうが安く済みますが、問題はメモリです。そこで、2つを同じ環境で動かして実測しました。
結論:4GB でも動くが、8GB を勧める
アイドル時の合計は約2.31GiB でした。内訳は、Dify が約1.94GiB、n8n が約369MiB、2つで共有する Caddy が13MiB です。
- 4GB のプランでも起動はします。ただし余裕は約42%で、ここから OS の分、Dify の起動時の上積み、n8n のワークフローの実行分が引かれていきます。
- Dify 単体では、再起動の直後にアイドル時より約200MiB 多く使いました(Dify の実測)。単純に足すと約2.5GiB になります(同居させた状態でのピークは測っていないため、これは推定です)。
- n8n 公式は、扱うデータの量やノードの数、同時に動くワークフローの数に応じてメモリが増えると説明しています。
本番として使い続けるなら 8GB のプランが安心です。4GB で始める場合は、docker stats で使用量を時々確認してください。
構成:Caddy を1つにまとめる
Dify も n8n も、単体で構築する記事では、それぞれの前に Caddy を置きました。同じサーバーでは 80番と443番を1つのプログラムしか使えないため、Caddy を1つにまとめ、ドメインで振り分けます。
┌──> Dify の nginx(dify.example.com)
インターネット ──> Caddy ──┤
└──> n8n(n8n.example.com)
Caddy は、Dify と n8n のそれぞれの Compose が作るネットワークに参加します。
手順1:Dify と n8n をそれぞれ起動する
Dify はDify を VPS にセルフホストする手順のとおり、公式の構成に上書き用のファイルを足して、ポートを外に公開しない状態で起動します。
n8n はn8n を Docker でセルフホストする手順の compose.yaml から、caddy のサービスとボリュームを外したものを使います。手元では、n8n 側の Caddy を停止した状態で測りました。
services:
n8n:
image: docker.n8n.io/n8nio/n8n:2.44.5
restart: unless-stopped
expose:
- "5678"
environment:
- N8N_HOST=${N8N_DOMAIN}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- N8N_WEBHOOK_URL=https://${N8N_DOMAIN}/
- NODE_ENV=production
- GENERIC_TIMEZONE=Asia/Tokyo
- TZ=Asia/Tokyo
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
- N8N_RESTRICT_FILE_ACCESS_TO=/files
volumes:
- n8n_data:/home/node/.n8n
- ./local-files:/files
volumes:
n8n_data:
手順2:共有の Caddy を起動する
別のディレクトリ(例:~/caddy)に、次のファイルを作ります。
compose.yaml:
services:
caddy:
image: caddy:2.11.7
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
environment:
- DIFY_DOMAIN=${DIFY_DOMAIN}
- N8N_DOMAIN=${N8N_DOMAIN}
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
networks:
- dify
- n8n
networks:
dify:
external: true
name: docker_default
n8n:
external: true
name: n8n_default
volumes:
caddy_data:
caddy_config:
Caddyfile:
{$DIFY_DOMAIN} {
reverse_proxy nginx:80
}
{$N8N_DOMAIN} {
reverse_proxy n8n:5678
}
.env:
DIFY_DOMAIN=dify.example.com
N8N_DOMAIN=n8n.example.com
networks の名前は「Compose を起動したディレクトリ名_default」です。上の例は、Dify を dify/docker、n8n を n8n というディレクトリで起動した場合の名前です。docker network ls で確認して合わせてください。2つのドメインの A レコードは、どちらも VPS の IP アドレスに向けます。
docker compose up -d
手元で確かめた結果
ドメインの代わりに dify.localhost と n8n.localhost、Caddy の内部証明書を使って、同じ構成を動かしました。
| 確認したこと | 結果 |
|---|---|
dify.localhost へのアクセス |
Dify に転送された(ステータス 307 で画面へリダイレクト) |
n8n.localhost へのアクセス |
n8n のエディターが開いた(ステータス 200) |
| n8n のヘルスチェック | {"status":"ok"} |
| 同時に動いたコンテナ | Dify 15個(初期設定用の1個は終了)、n8n 1個、Caddy 1個 |
同居させるときの注意
- アップデートは片方ずつ行い、終わるたびに両方が動いているかを確認します。
- バックアップの対象が増えます。 Dify の
volumesディレクトリと、n8n のボリューム(暗号鍵を含む)を、それぞれ取ってください。 - メモリが足りなくなると、Linux はプロセスを強制終了します。 どちらかが突然止まる場合は、メモリ不足を疑ってください。
docker statsで使用量を、dmesgで強制終了の記録を確認できます。