n8n × Docker Compose 構築ガイド|コピペで動くYAMLと運用のコツ

eye 1 14

月500円で、Zapier相当の自動化環境が手に入る

001 1

n8nとは何かを調べて、こう思った人は多いはずです。

「セルフホストなら無料? じゃあ自分のVPSで動かせばいいのか」

そのとおりです。

VPS代だけで、ノード数もワークフロー数も無制限。

Zapierで月$20〜$50かかっていた処理が、月500円のサーバーで回ります。

ただ、いざ構築しようとすると壁にぶつかります。

公式ドキュメントは英語。

Docker Composeの設定例はあちこちに散らばっている。

どれが最新で、どれが正しいのか分からない。

正直、私も最初は半日溶かしました。

この記事では、その「散らばった情報」を1箇所にまとめます。

コピペで動く `docker-compose.yml`、`.env`、`Caddyfile` の3点セット。

そして3ヶ月VPSで運用してきた実体験ベースのノウハウです。

前提条件

始める前に、以下が揃っていることを確認してください。

項目条件
VPSUbuntu 22.04以降(Debian系でもOK)
スペック最低1 vCPU / 2 GB RAM / 20 GB SSD
ドメイン自分のドメインがあり、DNSのAレコードを設定できる
DockerDocker EngineとDocker Composeが入っている

VPSはどこでも構いません。

私はHetznerのCX22(EUR 3.79/月、約600円)を使っています。

2 vCPU、4 GB RAM、40 GB NVMe SSD。n8nには十分すぎるスペックです。

Dockerがまだ入っていない場合は、公式の手順でインストールしてください。

bash
# Docker公式のインストールスクリプト(Ubuntu)

curl -fsSL https://get.docker.com | sh

sudo usermod -aG docker $USER

n8n Docker Composeの設定ファイル一式

002 1

これが核です。

以下の3ファイルをVPS上の同じディレクトリに置きます。

ディレクトリ構成

/opt/n8n/

├── docker-compose.yml

├── .env

└── caddy_config/

└── Caddyfile

まず作業ディレクトリを作ります。

bash
sudo mkdir -p /opt/n8n/caddy_config

cd /opt/n8n

docker-compose.yml

yaml
services:

postgres:

image: postgres:16-alpine

restart: unless-stopped

environment:

- POSTGRES_USER=${POSTGRES_USER}

- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}

- POSTGRES_DB=${POSTGRES_DB}

volumes:

- postgres_data:/var/lib/postgresql/data

healthcheck:

test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]

interval: 10s

timeout: 5s

retries: 5

shm_size: 128mb

n8n:

image: docker.n8n.io/n8nio/n8n

restart: always

depends_on:

postgres:

condition: service_healthy

environment:

- DB_TYPE=postgresdb

- DB_POSTGRESDB_HOST=postgres

- DB_POSTGRESDB_PORT=5432

- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}

- DB_POSTGRESDB_USER=${POSTGRES_USER}

- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}

- N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}

- N8N_PORT=5678

- N8N_PROTOCOL=https

- NODE_ENV=production

- WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/

- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}

- TZ=${TZ}

- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}

- EXECUTIONS_DATA_PRUNE=true

- EXECUTIONS_DATA_MAX_AGE=168

- N8N_DEFAULT_BINARY_DATA_MODE=filesystem

- N8N_DIAGNOSTICS_ENABLED=false

volumes:

- n8n_data:/home/node/.n8n

- ${DATA_FOLDER}/local_files:/files

caddy:

image: caddy:latest

restart: unless-stopped

ports:

- "80:80"

- "443:443"

environment:

- SSL_EMAIL=${SSL_EMAIL}

- SUBDOMAIN=${SUBDOMAIN}

- DOMAIN_NAME=${DOMAIN_NAME}

volumes:

- caddy_data:/data

- ${DATA_FOLDER}/caddy_config:/config

- ${DATA_FOLDER}/caddy_config/Caddyfile:/etc/caddy/Caddyfile

volumes:

postgres_data:

n8n_data:

caddy_data:

20行ちょっとのYAMLに見えますが、これだけでn8n + データベース + SSL付きリバースプロキシが揃います。

.env

bash
POSTGRES_USER=n8n

POSTGRES_PASSWORD=ここに強力なパスワードを入れる

POSTGRES_DB=n8n

DATA_FOLDER=/opt/n8n

DOMAIN_NAME=example.com

SUBDOMAIN=n8n

SSL_EMAIL=your-email@example.com

GENERIC_TIMEZONE=Asia/Tokyo

TZ=Asia/Tokyo

N8N_ENCRYPTION_KEY=ここに64文字のランダム文字列を入れる

パスワードと暗号化キーは、以下のコマンドで生成できます。

bash
# パスワード生成(32文字)

openssl rand -base64 32

# 暗号化キー生成(64文字)

openssl rand -hex 32

`DOMAIN_NAME` と `SUBDOMAIN` は自分の環境に合わせて書き換えてください。`n8n.example.com` でアクセスする想定です。

Caddyfile

{

email {$SSL_EMAIL}

}

{$SUBDOMAIN}.{$DOMAIN_NAME} {

reverse_proxy n8n:5678 {

flush_interval -1

}

}

たった7行。

でもこれだけでSSL証明書の自動取得と自動更新が動きます。

Nginxで同じことをやろうとすると、certbotの設定で倍の手間がかかります。

`flush_interval -1` は見落としがちな設定です。

これがないと、長時間実行するワークフローの途中で接続が切れます。

n8n固有の罠なので、忘れずに入れてください。

各設定の解説

YAML全体をコピペしたら動きますが、「なぜこの設定なのか」を知っておくと、トラブル時に自分で対処できます。

DB_TYPE=postgresdb

ここ、最も多い設定ミスです。

`postgres` ではなく `postgresdb`。n8n独自の命名規則なので、一般的なDocker Composeの感覚で `postgres` と書くと接続エラーになります。

これだけで1時間ハマった人を何人か見ています。

N8N_ENCRYPTION_KEY

n8nはワークフロー内のAPIキーやパスワードを暗号化して保存します。

この鍵を紛失すると、保存済みのクレデンシャルがすべて復号不可能になります。

つまり、全ての外部サービス接続を最初からやり直し。

`.env` ファイルのバックアップは必ず取ってください。

EXECUTIONS_DATA_PRUNE と MAX_AGE

実行ログを168時間(7日)で自動削除する設定です。

これがないと、データベースが際限なく肥大化します。

個人用途なら7日で十分です。

N8N_DEFAULT_BINARY_DATA_MODE=filesystem

画像やPDFなどのバイナリデータをデータベースではなくファイルシステムに保存します。

メモリ消費を大幅に抑えられるので、2 GB RAMのVPSでは必須の設定です。

起動と初期設定

ここまで準備できたら、あとは3ステップです。

1. DNSを設定

ドメインのDNS管理画面で、Aレコードを追加します。

タイプ: A

名前: n8n(サブドメイン)

値: VPSのIPアドレス

TTL: 300

2. 起動

bash
cd /opt/n8n

docker compose up -d

初回はイメージのダウンロードがあるので2〜3分かかります。

bash
# ログを確認

docker compose logs -f

PostgreSQLのヘルスチェックが通り、n8nが `Editor is now accessible via: https://n8n.example.com` と表示されたら成功です。

3. ブラウザでアクセス

`https://n8n.example.com` を開きます。

初回はオーナーアカウントの作成画面が表示されます。

メールアドレスとパスワードを設定すればn8nのダッシュボードに入れます。

ここまで、慣れれば10分。初めてでも30分あれば終わります。

3ヶ月運用して分かったこと

004 2

「構築できた」と「安定運用できている」の間には、けっこう距離があります。

3ヶ月動かしてきて実感したことを共有します。

リソース消費は驚くほど少ない

HetznerのCX22(2 vCPU / 4 GB RAM)で、n8n + PostgreSQL + Caddyの3コンテナを動かしています。

CPU使用率: 平均2〜5%

メモリ使用量: 約800MB〜1.2GB

ディスク使用量: 約3GB(ログ自動削除あり)

ワークフローが10個程度なら、1 vCPU / 2 GB RAMでも問題なく動くと思います。

ただし、メモリ2 GBギリギリだとバイナリ処理(PDF生成など)でOOM Killerに殺されることがあるので、`N8N_DEFAULT_BINARY_DATA_MODE=filesystem` は必ず設定してください。

バックアップは週1のcronで十分

bash
# /opt/n8n/backup.sh

#!/bin/bash

docker compose -f /opt/n8n/docker-compose.yml exec -T postgres pg_dump -U n8n n8n | gzip > /opt/n8n/backups/n8n-db-$(date +%Y%m%d).sql.gz

# 30日以上古いバックアップを削除

find /opt/n8n/backups -name "*.sql.gz" -mtime +30 -delete
bash
# crontab -e で追加

0 3 * * 0 /opt/n8n/backup.sh

毎週日曜3時にバックアップ、30日で古いものを削除。

これで十分です。

正直、バックアップの仕組みを作ったのは構築から2週間後でした。

その間にワークフローを10個作り込んでから「これ消えたら終わりだな」と気づきました。

最初から設定しておくことをおすすめします。

アップデートは2コマンド

bash
cd /opt/n8n

docker compose pull && docker compose up -d

これだけ。

ダウンタイムは数秒です。

ただし、メジャーアップデート(1.x → 2.xなど)の場合はリリースノートを確認してください。

DBマイグレーションが含まれることがあります。

トラブルシューティング

3ヶ月の間に遭遇した(または相談された)トラブルをまとめます。

DB接続エラー

ERROR: connect ECONNREFUSED 127.0.0.1:5432

99%の原因は `DB_TYPE` の設定ミスです。

bash
# .envを確認

# ❌ DB_TYPE=postgres

# ✅ DB_TYPE=postgresdb(n8nの設定ファイルではなく、docker-compose.ymlのenvironment)

本記事のYAMLではdocker-compose.yml内に直接 `DB_TYPE=postgresdb` と書いているので、コピペしていれば発生しません。

SSL証明書が取得できない

ERROR: challenge failed: ACME challenge not completed

確認ポイントは2つ。

  1. DNS: Aレコードが正しく設定されているか(`dig n8n.example.com` で確認)
  2. ポート: VPSのファイアウォールで80番と443番が開いているか
bash
# ポート確認

sudo ufw status

# 開いていなければ

sudo ufw allow 80/tcp

sudo ufw allow 443/tcp

パーミッションエラー

Error: EACCES: permission denied

n8nコンテナはUID 1000で動作します。ボリュームのオーナーを合わせてください。

bash
sudo chown -R 1000:1000 /opt/n8n/local_files

Webhookが動かない

外部サービスからのWebhookが届かない場合、`.env` の `WEBHOOK_URL` を確認してください。

bash
# ❌ よくある間違い

WEBHOOK_URL=http://n8n.example.com/ # httpになっている

WEBHOOK_URL=https://n8n.example.com # 末尾スラッシュがない

# ✅ 正しい

WEBHOOK_URL=https://n8n.example.com/

まとめ:次はワークフローを組もう

ここまでの手順で、VPS上にn8nのDockerセルフホスト環境が動いているはずです。

振り返ると、必要だったのは3つのファイルだけでした。

  1. docker-compose.yml — n8n + PostgreSQL + Caddyの3サービス定義
  2. .env — パスワード、ドメイン、暗号化キーの設定
  3. Caddyfile — SSL自動化のリバースプロキシ設定

月500〜600円のVPS代だけで、ノード数もワークフロー数も制限なし。

Zapierの無料プランで5つのワークフローに悩んでいたのが嘘みたいです。

サーバーが動いたら、次は「何を自動化するか」です。

n8nで何を自動化すればいい? 日々の”観察”から見つける自動化のタネでは、自動化対象の見つけ方を解説しています。

また、n8n以外の選択肢も気になるなら、AI自動化ツール4強比較も参考にしてみてください。

ぶっちゃけ、セルフホストの自由度を知ってしまうと他のツールには戻れません。

参考になれば幸いです。

n8nシリーズの記事はこちら