自動化

n8n docker:Composeで建てる本番構成とHTTPS公開・更新・バックアップ手順

n8n docker:Composeで建てる本番構成とHTTPS公開・更新・バックアップ手順

n8nをDockerで動かすだけなら、docker runの1行で画面が開きます。業務で使い続けるときに差が出るのは、その先の設定です。Webhookの公開URL、認証情報を復号する暗号鍵の置き場所、版を固定した更新、PostgreSQLのバックアップがそろって、初めてセルフホストは本番に耐えます。この記事では、ローカルでの起動からDocker Composeによる本番構成、n8n 3.0へ上げる前の確認、キューモードへ進む条件までを、2026年11月6日時点の公式ドキュメントと設定ファイルで示します。

まとめ:n8nのDocker運用は版固定・暗号鍵の退避・公開URLの設定で決まる

ローカルで試すなら、名前付きボリュームを/home/node/.n8nに割り当ててdocker runで起動すれば足ります。社内で継続利用するなら、PostgreSQL・n8n・リバースプロキシの3サービスをDocker Composeで定義し、N8N_WEBHOOK_URLに公開URLを入れます。

運用で外せないのは2つです。イメージのタグを2.46.6のように版で固定すること。暗号鍵とデータベースを必ず組で退避すること。n8n 3.0は2026年10月27日にベータが公開され、安定版は12月初旬の予定です。3.xから2.xへは戻せないので、上げる前に完全なバックアップを取ります。キューモードは、実行が詰まり始めてから検討すれば間に合います。

docker runでn8nをローカルに立てて動作とデータ保存先を確かめる手順

最初の1台は、手元のPCで動かして構造をつかむのが近道です。Mac・Windows・LinuxのいずれもDocker Desktopを入れればDocker EngineとComposeがそろうと、n8n公式のDocker導入ページは案内しています。

名前付きボリュームn8n_dataを割り当てて5678番で起動するコマンド

公式手順と同じ形で、ボリュームの作成と起動を行います。タグはGitHubのリリース一覧で2026年11月4日にLatestとなった2.46.6に固定しました。

# データを残すボリュームを作り、2.46.6 を起動する
docker volume create n8n_data

docker run -it --rm --name n8n \
  -p 5678:5678 \
  -e GENERIC_TIMEZONE="Asia/Tokyo" \
  -e TZ="Asia/Tokyo" \
  -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
  -v n8n_data:/home/node/.n8n \
  n8nio/n8n:2.46.6

起動したらhttp://localhost:5678を開き、オーナーアカウントを作ります。GENERIC_TIMEZONEを省くと、スケジュール実行の基準がニューヨーク時間になります。毎朝9時のつもりで組んだCronが日本時間の22時か23時に動く事故を防ぐため、ローカルでも必ず指定してください。

.n8nフォルダに入る暗号鍵とSQLiteを消さないための確認手順

何も指定しなければ、データベースは組み込みのSQLiteです。DBファイルも、認証情報を暗号化する鍵も、ボリューム内の.n8nに置かれます。鍵は初回起動時に自動で生成され、configファイルに書き込まれると暗号鍵の設定ページに記載があります。

# 生成された鍵を確認する(別環境へ移すときに同じ値を使う)
docker exec -u node n8n cat /home/node/.n8n/config

# ボリュームの実体がどこにあるかを確認する
docker volume inspect n8n_data

--rmを付けてもコンテナが消えるだけで、ボリュームは残ります。危ないのはdocker volume rmやdocker compose down -vです。鍵ごとボリュームが消え、ワークフローを別途エクスポートしていても、登録済みの認証情報は戻りません。

ローカル環境で外部サービスのWebhookが届かない理由と検証の進め方

ローカルのn8nでWebhookノードを置くと、URLはhttp://localhost:5678/webhook-test/...になります。SlackやGitHubなどのSaaSからは、このアドレスに届きません。

ローカルで済むのは、ワークフローの組み立てと、curlで自分から送る動作確認までです。外部サービスからの受信を試す段階に来たら、ドメインを割り当てた検証サーバーを1台用意し、次章の構成で建てます。外部から直接届く口を手元のPCに開けるより、片付けも権限管理も簡単です。

Docker ComposeでPostgreSQLとCaddyをつなぐ本番構成の書き方

公式のDocker Compose手順はリバースプロキシにTraefikを使い、DBはSQLiteのままです。ここでは設定が短く読めるCaddyに置き換え、DBをPostgreSQLにした3サービス構成を示します。前提は、サーバーのIPアドレスを指すAレコードを作成済みで、80番と443番が外から届くことです。

.envに暗号鍵とDB接続情報を置き版番号を固定する設定ファイル

秘密情報と版番号は.envに集め、compose.yamlには書きません。暗号鍵を自分で決めておくと、ボリュームを失っても鍵だけは手元に残せます。

# .env(Git に入れない。権限は 600 にする)
N8N_VERSION=2.46.6
N8N_DOMAIN=n8n.example.co.jp
N8N_ENCRYPTION_KEY=ここに openssl rand -hex 32 の出力を貼る
POSTGRES_USER=n8n
POSTGRES_PASSWORD=ここに長いランダム文字列を貼る
POSTGRES_DB=n8n

すでに動いているn8nをこの構成へ移す場合は、新しい鍵を作らず、前章のconfigにある値をそのまま入れます。鍵が変わると、DB内の認証情報を復号できません。

compose.yamlによるn8n・PostgreSQL・Caddyの3サービス定義例

PostgreSQLの設定は、n8n公式のn8n-hostingリポジトリにある構成例と同じくpostgres:18を使い、PGDATAを固定しています。18系でデータディレクトリの既定値が変わったため、固定しておくとメジャー版を上げてもボリュームの割り当てがずれません。

services:
  postgres:
    image: postgres:18
    restart: always
    environment:
      - POSTGRES_USER
      - POSTGRES_PASSWORD
      - POSTGRES_DB
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - db_storage:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 5s
      retries: 10

  n8n:
    image: n8nio/n8n:${N8N_VERSION}
    restart: always
    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_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_HOST=${N8N_DOMAIN}
      - N8N_PROTOCOL=https
      - N8N_WEBHOOK_URL=https://${N8N_DOMAIN}/
      - N8N_PROXY_HOPS=1
      - GENERIC_TIMEZONE=Asia/Tokyo
      - TZ=Asia/Tokyo
      - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
    volumes:
      - n8n_storage:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy

  caddy:
    image: caddy:2
    restart: always
    ports:
      - "80:80"
      - "443:443"
    environment:
      - N8N_DOMAIN=${N8N_DOMAIN}
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config

volumes:
  db_storage:
  n8n_storage:
  caddy_data:
  caddy_config:

n8nの5678番はportsで公開していません。外からはCaddy経由でしか届かない形にしておくと、HTTPのまま管理画面が露出する事故を防げます。起動はdocker compose up -d、状態の確認はdocker compose psで行います。

CaddyfileでLet’s Encryptの証明書を自動取得してHTTPS化する設定

Caddyは、サイトアドレスにドメイン名を書くだけで証明書の取得と更新を自動で行います。発行元にLet’s EncryptとZeroSSLを使う仕組みはCaddyのAutomatic HTTPSに、転送先の書き方はreverse_proxyディレクティブに記載があります。

# Caddyfile(compose.yaml と同じディレクトリに置く)
{$N8N_DOMAIN} {
	reverse_proxy n8n:5678
}

{$N8N_DOMAIN}はコンテナに渡した環境変数を読む書き方です。証明書の取得に失敗したときは、docker compose logs caddyでACMEのエラーを確認します。原因の多くは、DNSの反映待ちか、80番がファイアウォールで閉じていることです。

Webhookの公開URLとリバースプロキシ配下で設定する環境変数の一覧

プロキシの裏に置いたn8nは、自分が外からどのURLで見えているかを知りません。それを教えるのが、次の環境変数です。

N8N_WEBHOOK_URLとWEBHOOK_URLの関係と2.35.0からの非推奨

Webhookノードに表示されるURLのベースを決めるのがN8N_WEBHOOK_URLです。Endpointsの環境変数一覧では、旧名のWEBHOOK_URLは2.35.0で非推奨となり、別名として動くものの起動時に警告ログを出すとされています。新名が使えるのは2.30.0以降です。

古い解説記事の多くはWEBHOOK_URLのままです。2.30.0より前の版を固定している環境でなければ、新名で書いてください。未設定のままだと画面にhttp://localhost:5678/webhook/...が出て、そのURLを外部サービスに登録しても届きません。

N8N_PROXY_HOPSとN8N_HOSTを合わせないと起きる表示URLのずれ

Deploymentの環境変数一覧によると、N8N_HOSTの既定はlocalhost、N8N_PROTOCOLの既定はhttp、N8N_PROXY_HOPSの既定は0です。Caddyを1段挟む構成ではN8N_PROXY_HOPS=1とし、ホスト名とプロトコルも公開側の値に合わせます。

ロードバランサーの後ろにさらにCaddyを置くなら、段数は2です。招待メールやSAMLのリダイレクト先がエディターのURLと食い違うときは、N8N_EDITOR_BASE_URLにも公開URLを入れます。

Webhookの受信上限16MiBと用途別に変える環境変数の早見表

大きなファイルをWebhookで受ける業務では、受信上限にも注意が要ります。公式ドキュメントの既定値を用途別に並べました。

設定項目 既定値 変える場面
N8N_WEBHOOK_URL 未設定 プロキシ配下で公開URLを示す
N8N_PROXY_HOPS 0 プロキシを挟む段数に合わせる
N8N_PAYLOAD_SIZE_MAX 16MiB 大きなJSONを受ける
添付ファイルのサイズ上限 200MiB 添付ファイルを受ける
N8N_ENDPOINT_WEBHOOK webhook URLのパスを社内規約に合わせる

表の「添付ファイルのサイズ上限」は、環境変数N8N_FORMDATA_FILE_SIZE_MAXを指します。上限を上げるとメモリとCPUの消費も増え、反映には再起動が必要です。Caddy側に別の上限を設けている場合は、そちらも合わせて見直します。

暗号鍵とPostgreSQLを両方退避するバックアップと復元の順番

公式のバックアップと復元のページは、完全なバックアップの対象を.n8nフォルダ、外部DB、外部ストレージ、カスタムノードのディレクトリとしています。PostgreSQL構成で最低限そろえるのは、DBのダンプと暗号鍵です。

pg_dumpとCLIのexport:workflowで取る毎日のバックアップスクリプト

DBはPostgreSQLのpg_dumpで丸ごと、ワークフローと認証情報はn8nのCLIでJSONとしても取ります。JSONはGitで差分を追えるので、誰がいつフローを変えたかを後から確かめられます。

#!/bin/sh
# backup.sh(compose.yaml と同じディレクトリで cron から毎日実行する)
set -eu
D=backups/$(date +%F)
mkdir -p "$D"

# DB 全体(ユーザー・実行履歴・変数も含む)
docker compose exec -T postgres sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' > "$D/n8n.dump"

# ワークフローと認証情報を個別ファイルで出す(認証情報は暗号化されたまま)
docker compose exec -T -u node n8n n8n export:workflow --backup --output=/home/node/bk/workflows/
docker compose exec -T -u node n8n n8n export:credentials --backup --output=/home/node/bk/credentials/
docker compose cp n8n:/home/node/bk "$D/json"
docker compose exec -T -u node n8n rm -rf /home/node/bk

# 14日より古い世代を消す
find backups -mindepth 1 -maxdepth 1 -type d -mtime +14 -exec rm -rf {} +

--backupは--all --pretty --separateの短縮形です。--decryptedを付けると平文の認証情報が出力されるため、定期バックアップでは使いません。

CLIエクスポートに含まれないユーザー・実行履歴・暗号鍵の扱い

CLIのエクスポートには、ユーザーとロール、実行履歴とログ、変数、暗号鍵を含むインスタンス設定が入りません。JSONだけでは、インスタンスを元の姿に戻せないということです。

暗号化されたまま出した認証情報は、同じ鍵が無ければ読めません。鍵はバックアップと同じ場所に置かず、パスワード管理ツールなど別の保管先に入れます。ダンプと鍵が同じディスクにあると、1回の障害や流出で両方を失います。

別サーバーへ移すときの停止・config復元・DBリストアの順序と動作確認

公式ページの復元手順は、n8nの停止、.n8nの復元、DBの復元、環境変数の復元、起動の順です。Compose構成に当てはめると次のようになります。

  1. docker compose stop n8nでn8nだけを止める
  2. .envのN8N_ENCRYPTION_KEYを移行元と同じ値にする
  3. docker compose exec -T postgres pg_restore -U n8n -d n8n --clean --if-exists < n8n.dumpでDBを戻す
  4. docker compose up -dで起動し、認証情報を1件開いて接続テストを通す

確認は、認証情報の画面で「接続できた」まで見ます。ワークフロー一覧が表示されても、鍵が違えば認証情報の復号で失敗するからです。CLIで取り込んだワークフローは既定で非アクティブになるので、本番のトリガーを有効にし直す作業も手順に入れておきます。

版を固定したアップデート運用とn8n 3.0へ上げる前の移行チェック

2026年11月6日に確認したDocker Hubでは、n8nio/n8nのlatest・stable・2.46.6が同じダイジェストを指しています。latestのまま運用すると、安定版チャネルが切り替わった日のpullで、意図しない版に上がります。

docker compose pullで2.x系のパッチ版へ上げる手順と確認点

リリースは数日おきに出ており、11月2日から4日だけでも2.46.4・2.46.5・2.46.6が公開されました。毎回追う必要はありません。月1回など周期を決め、リリースノートを読んでから.envの版を書き換えます。

# 1. 先にバックアップを取る
./backup.sh

# 2. .env の N8N_VERSION を書き換えてから取得・再作成する
docker compose pull n8n
docker compose up -d n8n

# 3. 起動ログで版と DB マイグレーションの完了を確かめる
docker compose logs --tail=100 n8n

上げた直後は、スケジュール実行と本番Webhookをそれぞれ1本ずつ手で動かします。問題が出たらN8N_VERSIONを戻してup -dし直しますが、DBマイグレーションが走った後は戻らないこともあるため、手順1のダンプが最後の砦になります。

3.0の破壊的変更でDocker運用者が見直す環境変数とCodeノード

v3.0のBreaking changesには、Docker運用者に直接効く変更が並んでいます。n8n公式ブログの3.0発表は、2.xへは戻せず、戻すにはバックアップからの復元しかないと明言しています。

  • npmとnpx n8nでの導入が終わり、セルフホストはDocker前提になる
  • CodeノードのタイムアウトN8N_RUNNERS_TASK_TIMEOUTの既定が300秒から60秒に縮む
  • OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERSなどの環境変数が削除される
  • N8N_UNVERIFIED_PACKAGES_ENABLEDの既定がfalseになり、未検証のコミュニティノードが止まる
  • 暗号鍵のローテーションが既定で有効になる

実務で先に手を付けるのは、1分を超えるCodeノードの洗い出しです。設定画面のMigration Reportで影響を受けるワークフローを確認し、必要ならN8N_RUNNERS_TASK_TIMEOUTを明示してください。Chat Hubを使っているなら、3.xで維持するにはN8N_ENABLED_MODULESにchat-hubを加えます。経緯はn8n Chat Hubの使い方と3.0で既定オフになる前の対応にまとめています。

3.xの安定版が出ても、最初の数パッチは見送ってかまいません。検証用のComposeを本番ダンプから復元して上げ、主要なフローが通ったのを見てから本番に進めます。

キューモードとワーカー分離に進むべき条件と単一コンテナで足りる規模

ここまでの構成は、1つのn8nコンテナが画面もWebhookも実行も受け持ちます。実行をワーカーへ分けるのがキューモードです。

EXECUTIONS_MODE=queueとRedisで構成するワーカーの最小設定

キューモードの公式ページによると、メインと全ワーカーでEXECUTIONS_MODE=queueを設定し、Redisの接続先をQUEUE_BULL_REDIS_HOSTで示します。ワーカーの同時実行数は既定10で、公式は5以上を推奨しています。前出のcompose.yamlに足す差分は次のとおりです。

  redis:
    image: redis:7-alpine
    restart: always
    volumes:
      - redis_storage:/data

  n8n-worker:
    image: n8nio/n8n:${N8N_VERSION}
    restart: always
    command: worker --concurrency=5
    environment:
      # n8n サービスと同じ DB_* と N8N_ENCRYPTION_KEY をすべて渡す
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
    depends_on:
      - redis
      - postgres

# n8n サービスの environment にも EXECUTIONS_MODE=queue と QUEUE_BULL_REDIS_HOST=redis を追加し、
# volumes に redis_storage: を足す

暗号鍵はメイン・ワーカー・Webhookプロセッサーのすべてで同じ値にします。違うと、ワーカーがDB内の認証情報を読めません。公式の構成例はさらにn8nio/runnersイメージでCodeノード用の外部ランナーを分けており、本番で組むときはそちらを手本にします。なお、構成例にあるOFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=trueは3.0で削除される変数です。

単一コンテナで運用を続けてよい場面とキューモードを見送る判断

キューモードに進むのは、次のどちらかが起きてからで十分です。

  • 重い実行の最中に、エディターの操作やWebhookの応答が目に見えて遅くなる
  • 同じ時刻に起動するスケジュール実行が重なり、終了時刻が後ろへずれ込む

部署内の数十本のフローを1時間おきに回す規模なら、単一コンテナとPostgreSQLで足ります。Redisとワーカーを足すと、監視対象と更新手順が倍になり、鍵の配布先も増えます。SQLiteのまま分散させる構成は公式に非対応なので、PostgreSQLへの移行が先です。複数のメインプロセスを並べる冗長化は、セルフホストではEnterpriseライセンスが条件になります。

セルフホストを採らずn8n Cloudや外部委託を選ぶべき社内体制

セルフホストの費用は、サーバー代よりも人の時間にかかります。月1回の更新とリリースノートの確認、毎日のバックアップの監視、3.0のような移行の検証を、担当者の通常業務に組み込めるかで判断します。

Dockerとリバースプロキシを触れる人が社内に1人しかいないなら、セルフホストは見送ります。その人が異動した時点で、鍵の保管先も更新の手順も分からなくなるからです。この場合は、料金体系とプランの違いをn8nとは?読み方・料金・商用利用の範囲と3.0で変わる始め方で確かめ、n8n Cloudで始めるほうが安全です。社内システムとのAPI連携まで含めて設計と構築を任せたい場合は、一創のiPaaS導入支援でn8nを含むツールの選定から対応しています。

よくある質問:n8nのDocker導入で多い保存先・Windows・更新頻度の疑問

n8nをDockerで導入するときに、よく聞かれる質問をまとめました。

WindowsやMacのDocker Desktopでもn8nは動きますか?

動きます。公式の前提条件はDocker Desktopで、Mac・Windows・Linuxのいずれにも対応しています。手元で組み立てと動作確認を行い、外部サービスからWebhookを受ける段階でサーバーへ移すのが現実的な分担です。PCのスリープ中はスケジュール実行も止まるので、業務の定期処理をPCのDocker Desktopに任せるのは避けてください。

SQLiteのままで本番運用しても問題ありませんか?

1人で使う小さな環境なら動きますが、社内の共有基盤にするならPostgreSQLを選びます。キューモードでSQLiteを使う分散構成は公式に非対応で、後から規模を広げられません。SQLiteは.n8nフォルダ内のファイルなので、整合性を保つにはn8nを止めてからコピーする必要があり、無停止のバックアップも取りにくくなります。

n8nのDockerイメージはどれくらいの頻度で更新されますか?

2026年11月2日から4日の3日間だけで、2.x系のパッチが3つ公開されました。並行して3.x系のプレリリースと1.x系の保守版も出ています。すべてを追う必要はなく、版をタグで固定し、月1回などの周期で上げる運用が扱いやすいでしょう。脆弱性の修正が告知された場合だけは周期を待たずに上げます。

コンテナを作り直してもワークフローは消えませんか?

docker compose downやup -dでの作り直しでは消えません。データは名前付きボリュームに残るためです。消えるのは、down -vでボリュームごと削除したときと、ボリュームを割り当てずに起動していたときです。後者に心当たりがあれば、止める前にCLIでワークフローと認証情報をエクスポートし、configの鍵を控えてください。

npxで動かしているn8nをDockerへ移すにはどうすればよいですか?

3.0ではnpmでの導入が終わるため、早めの移行が安全です。npx版のデータはホームディレクトリの.n8nにあるので、n8nを止めてそのフォルダを新しいボリュームへコピーするのが最も確実です。DBを入れ替える場合は、CLIでワークフローと認証情報を出力し、同じ暗号鍵を設定したDocker版へ取り込みます。

関連記事

お気に入りに入れた記事の一覧

一創の公式 SNS

X では毎朝の新着記事と IT ニュースの速報を、YouTube・TikTok・Instagram・LinkedIn・Facebook では記事の解説動画を配信しています。

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.11.05 テックブログ Linuxカーネルの脆弱性CVE-2026-98432:修正版の見分け方とnftablesの緩和策
  2. 2026.11.04 テックブログ CVE-2026-119977:WordPress更新中のRCEと安全な更新手順
  3. 2026.11.03 テックブログ クラブツーリズム不正アクセス:約432万件の対象確認と偽メールの見分け方・流出検知の設計
  4. 2026.10.29 テックブログ ソニー生命の情報漏洩38.5万件|ログインできない理由、再開状況と窓口の電話番号
  5. 2026.11.05 コラム 給与支払報告書とは?令和8年分の提出期限・書き方と源泉徴収票みなし提出への対応

RELATED POSTS 関連記事

目次