メインコンテンツへスキップ
見出し画像

VPSにn8nを立てたら、Dockerで3回ハマった話 ―Kubernetesのingressまで試して分かったこと

セルフホスト型のワークフロー自動化ツール「n8n」を自分のVPSに立てようとした週末、気づいたら丸2日が溶けていた。

「Dockerで簡単に動かせます」という公式ドキュメントの一文を信じてターミナルを開いたものの、実際にやってみるとコンテナは起動しない、リバースプロキシの設定は噛み合わない、データは消える……と、次から次へと壁が出てきた。同じようなところで詰まっている人が絶対いるはずだと思って、この記事を書いた。

Dockerで躓いた3つのポイントと、番外編としてKubernetes(k3s)+Ingressパターンまで試した結果をまとめている。どちらを選ぶか迷っている人にも参考になると思う。

────────────


目次

  1. この記事で扱うこと・扱わないこと

  2. n8nをDockerで立てる基本構成の確認

  3. ハマりポイント①:パーミッションエラーでコンテナが即死する

  4. ハマりポイント②:WebhookのURLが内部アドレスになってしまう

  5. ハマりポイント③:NginxのリバースプロキシでWebSocketが切れる

  6. データ永続化の落とし穴:「あれ、ワークフローが消えた」を防ぐ

  7. Kubernetes(k3s)でn8nを動かす ―Ingressパターンの詳細

  8. DockerComposeとk3s、結局どちらを選ぶか

  9. まとめ


この記事で扱うこと・扱わないこと

扱うこと


  • VPS(Ubuntu 22.04想定)でDockerを使ってn8nを立てるときにハマりやすいポイント

  • docker-compose構成のベストプラクティス

  • Nginx(またはTraefik)をリバースプロキシにする設定の注意点

  • k3s+Ingress Nginxでn8nをデプロイするパターンとトレードオフ

扱わないこと


  • n8nの使い方・ワークフローの作り方

  • AWS EKSやGKEなどのマネージドKubernetes

使っているVPSはConoHaとVultrを行き来しているが、どちらも基本的に同じ手順で動く。スペックの目安はvCPU 2コア、メモリ2GB以上あれば快適に動いた。

────────────


n8nをDockerで立てる基本構成の確認

まず前提として、n8nのDockerイメージはDockerHubで公開されている(n8nio/n8n)。公式ドキュメントにはdocker-composeの最小構成が載っているが、あれをそのままコピペすると後で詰まる部分がある。

最小限の構成はこうなる。

version: "3.8"

services:
n8n:
image: n8nio/n8n
restart: always
ports:
- "5678:5678"
environment:
- N8N_HOST=your-domain.example.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://your-domain.example.com/
volumes:
- n8n_data:/home/node/.n8n

volumes:
n8n_data:

一見シンプルに見える。でもここに落とし穴がいくつか潜んでいる。

────────────


ハマりポイント①:パーミッションエラーでコンテナが即死する

最初のハマりはこれだった。コンテナを起動すると数秒で落ちて、ログを見ると次のようなエラーが出ていた。

Error: EACCES: permission denied, mkdir '/home/node/.n8n'

原因

Dockerのnamed volumeではなく、ホストのディレクトリをマウントしているときによく起きる。ホストのディレクトリのオーナーがrootになっていて、コンテナ内のnodeユーザー(UID 1000)が書き込めない。

解決策

named volumeを使う場合は基本的に問題が起きにくいが、ホストディレクトリをマウントしたい(バックアップしやすくしたいなど)場合は事前にオーナーを変えておく。

mkdir -p /opt/n8n/data
chown -R 1000:1000 /opt/n8n/data

そしてcomposeのvolumes設定をこう書き換える。

volumes:
- /opt/n8n/data:/home/node/.n8n

これだけで即死ループから脱出できた。

『(ここに体験:「restart: always」のせいで気づかないまま再起動ループしていてdocker logsを見るまで理由が分からなかった話)』

ちなみにrestart: alwaysが設定してあるとコンテナが何度も再起動し続けるので、docker logs -f n8nでリアルタイムにログを追いかけるのが一番早い。docker compose psでSTATUSを見るだけだと「起動してる」ように見えてしまうことがある。

────────────


ハマりポイント②:WebhookのURLが内部アドレスになってしまう

n8nのワークフローでWebhookトリガーを使おうとすると、生成されるURLがhttp://localhost:5678/webhook/...になってしまう問題。外部サービス(SlackやGitHubなど)からのWebhookが受け取れない。

原因

環境変数WEBHOOK_URLが正しく設定されていないか、設定されていてもN8N_PROTOCOLと噛み合っていないことが多い。

必要な環境変数の整理

変数名 / 設定すべき値の例 / 役割

  • N8N_HOST … 設定すべき値の例:your-domain.example.com / 役割:n8nが認識するホスト名

  • N8N_PORT … 設定すべき値の例:5678 / 役割:n8nが使うポート

  • N8N_PROTOCOL … 設定すべき値の例:https / 役割:httpかhttpsか

  • WEBHOOK_URL … 設定すべき値の例:https://your-domain.example.com/ / 役割:Webhook URLのベース

末尾のスラッシュを忘れやすいので注意。WEBHOOK_URLの末尾にスラッシュがないと、Webhookのパスが正しく生成されない。

────────────

ここまでが無料で読める部分だ。次のセクションからは、リバースプロキシとの組み合わせで起きたSSL/HTTPSまわりの問題、データ永続化に関するよくある誤解、そしてKubernetes(k3s)でのデプロイパターンとIngressの設定を詳しく書いている。

 
 
AIと自動化で日々の『めんどう』を減らす実験を発信しています。n8nやローカルLLMの構築メモから、新NISAなどお金の話まで。初心者がつまずくポイントを、実体験ベースでやさしく。明日すぐ試せるネタを届けます。よければフォローを🤖📈

あなたへのおすすめ