Dockerとは何か:n8n初心者向けの最小限の必須知識

n8nをインストールする際に最も詰まりやすいのはn8n自体ではなく、その前にあるDockerだ。チュートリアル通りに5行のコマンドをコピペし、containerが起動し、画面で2、3クリックすれば使えるが、翌日戻ってくるとworkflowが全部消えている——原因はその5行の中に1つ足りないだけだ -v。

この記事ではn8nのインストールに必要な部分のDockerだけを扱う:image、container、volume、port。4つの単語だ。ネットワークモード、Compose、自分でimageをビルドする方法については、本当に必要になったときに学べばいい。前もって学んでも忘れるだけだ。

前提条件は1つだけ:ターミナルでコマンドを打てること、「port」とは何かを知っていること。Dockerに触れたことがなくても全く問題ない。

n8nが最終的にDockerに入れる理由

公式インストールページにはいくつかの方法が示されている:npmでグローバルインストール、npxで直接実行、Docker、デスクトップ版。最初の2つは最も軽く、1行 npm install -g n8n で完了するが、問題はn8nをマシン上のNodeに縛り付けることだ。n8nはNodeのバージョンに細かくこだわり、ドキュメントには20.19から24.xの範囲と書かれている。いつか別のプロジェクトのためにNodeを26に上げると、n8nもそれに連動して動かなくなり、エラーメッセージがわかりやすいとは限らない。

Dockerは発想を変えた:n8nとそれが依存するNode、システムライブラリ、タイムゾーンデータをすべて1つのパッケージにまとめ、このパッケージは誰のマシンでも同じように動く。わざわざ2.43.7のimageに入って確認したところ、Nodeは26.7.0で、ベースimageはAlpineだった。これらはホストマシンにNode 18が入っていようと26が入っていようと全く関係ない。

コストについてもはっきり言っておく。メンテナンスすべきものが一层増える:imageがディスクを占有し(2.43.7は解凍後1.8 GB)、問題が起きたら見るログが一箇所増え、アップグレードは「npm update」から「imageを差し替えて再実行」に変わる。自分としては価値があると思う——アップグレードの際は、tagを変更し、containerを削除し、再実行する、3分で済み、Nodeのバージョンを気にしなくていい。

ローカルで2日だけ遊ぶなら、Dockerは勧めない、npmの方が速い。長期的に動かすつもりなら、あるいは同僚に使わせるなら、直接Dockerを使え、遠回りするな。

四つの言葉:image、container、volume、port

image

imageは他人がビルド済みの読み取り専用パッケージで、中身はn8nを動かせる完全なファイルシステム一式だ。n8nio/n8n は名前、2.43.7 はタグ。同じ名前の下にたくさんのタグがぶら下がっていて、一つのタグが一つのバージョンに対応する。

タグに latestと書くのは「最新安定版」という意味だ。本番ではこう書くのは勧めない:ある日containerを再起動した際についでに新しいimageをpullしてしまい、挙動が変わっても、どこから調べればいいかすら分からない。バージョン番号は固定で書き、アップグレードは独立した作業として行え。

Docker Hub 上 n8nio/n8n 的 2.43.7 标签页,显示 docker pull 命令与压缩体积
Docker Hubのタグページは、一バージョン一行。2.43.7のamd64版は圧縮後260.51 MB、arm64は259.76 MB。右側のその docker pull が、君が叩くべき

container

imageは静的だ。docker run その後走り出したそのプロセスこそがcontainerと呼ばれる。containerはimageに書き込み可能なレイヤーを一層加えたもので、中で変更したものはすべてこのレイヤーに書かれる。containerを削除すれば、このレイヤーも一緒に消える——この一言が後のすべての罠の源だ。

卷

だからn8nのデータはcontainerの中に置いてはいけない。volumeはホストマシン上の一つのディレクトリで、Dockerが管理し、containerの特定のパスにmountされる。n8nが認識するパスは /home/node/.n8n、データベース、暗号化キー、イベントログはすべてそこにある。

数えてみた:owner アカウントを作成し終え、ワークフローを一度実行したばかりの .n8n ディレクトリで、5.5 MB。そのうち database.sqlite 1.5 MB、さらに 4 MB の -wal ファイルが1つ。これだけのもので、失えばすべてやり直しだ。

ポート

-p 5678:5678、コロンの左側がホスト側ポート、右側がコンテナ内ポート。コンテナ内の n8n は常に 5678 をリッスンする( N8N_PORTを変更しない限り)、外側で番号を変えたいなら左側だけを動かす:-p 8080:5678。

と書けば 127.0.0.1:5678:5678 ローカルホストにのみバインドされ、外部からは接続できない。テスト時はいつもこの書き方を使い、閉じ忘れを防いでいる。

まず Docker をインストールする

Ubuntu / Debian で最も手軽なのは公式のあのスクリプト:

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

公式リポジトリを追加し、docker-ce をインストールし、compose プラグインも入る。「curl で出てきたものをそのまま sh に食わせる」のが気になるなら、素直に apt 公式リポジトリの手順を踏む。手順は Docker ドキュメントにあり、少し長いだけ。

インストール後に2つのコマンドでバージョンを確認:

docker --version
# Docker version 29.1.3, build 29.1.3-0ubuntu3~24.04.2

私のこの 232 は Ubuntu 24.04 + Docker 29.1.3。24 でも 25 でもよく、コマンドに違いはない。

Docker はデフォルトで root または sudo が必要です。ユーザーを docker グループに追加すれば sudo 不要になると言う人もいますが、それは正しいものの、そのユーザーに root 権限を与えるのと同じことで、理由はセキュリティの節にあります。

n8n を起動する、3ステップ

ステップ1:ボリュームを作成

docker volume create n8n_data
# n8n_data

ボリューム名が返ってくれば作成完了です。このステップは省略しても、docker run に書けば -v n8n_data:/home/node/.n8n 自動で作成されます——ただし一度作成しておけば、本当に存在することを確認できます。

ステップ2:起動する

docker run -d 
  --name n8n 
  -p 127.0.0.1:5678:5678 
  -e TZ=Asia/Shanghai 
  -e GENERIC_TIMEZONE=Asia/Shanghai 
  -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true 
  -v n8n_data:/home/node/.n8n 
  n8nio/n8n:2.43.7

公式ドキュメントの元のコマンドと比べて、2箇所変更しました。

1つ目は -dを追加したことです。ドキュメントでは docker run -it --rmで、フォアグラウンドで実行するため、ターミナルを閉じるか Ctrl+C を押すと n8n が停止し、--rm ついでにコンテナも削除されます。デバッグ時にはこれで非常にすっきりしますが、長期運用には向きません。 -d を付けてバックグラウンドで待機させます。

もう1つはポートの前に 127.0.0.1:。ドキュメントには -p 5678:5678と書かれている。それは 0.0.0.0 にバインドするのと同じで、マシンにパブリック IP さえあれば、5678 をスキャンした誰でもあなたのログインページを見られる。私の 232 の 5678 は埋まっているので、実際に使っているのは -p 127.0.0.1:5681:5678で、マッピングの関係は同じだ。

2 つのタイムゾーン変数を両方とも設定する必要がある。TZ はコンテナのシステム時刻を管理し、GENERIC_TIMEZONE は n8n 自身が時刻をどう計算するかを管理する。Schedule Trigger が参照するのは後者だ。片方だけ設定すると TZ、スケジュールタスクは依然として UTC で動き、あなたが思っている朝 9 時は北京時間の 17 時になる。こういうことはログに異常を一切残さない。

ステップ 3:ログを見て、起動を待つ

docker logs -f n8n

初回起動時には数十件のデータベースマイグレーションが実行され、Starting migration ... 和 Finished migration ... が交互に流れる。正常だ。次の 2 行が出るまで待つ:

Version: 2.43.7

Editor is now accessible via:
http://localhost:5678

その http://localhost:5678 はコンテナ内部のアドレスで、ブラウザでは開けない。開けるのは http://服务器IP:5678、またはローカルマシン上の http://127.0.0.1:5678だ。この一文に騙された人は少なくない。初めて実行した私もそうだった。

2.43.7 は起動時にさらに 5 件の deprecation 警告を吐き、次のように述べる N8N_RUNNERS_MODE、N8N_UNVERIFIED_PACKAGES_ENABLED これらのデフォルト値は後で変更する。使用には影響しない、将来のバージョンのための布石だ。さらにもう一行 Failed to start Python task runner in internal mode. because Python 3 is missing from this system.——イメージに Python が入っていない、JS の Code ノードだけを使うなら全く気にする必要はない。

新容器里的 n8n 首次打开是 Set up owner account 页面
新しい container を初めて開くと、この「Set up owner account」になる。ワークフローはゼロ、すべてここから始めなければならない

アカウントを作成すれば入れる。このステップを volume に書き込まなければ意味がない——下の検証で本当にディスクに永続化されたかを確認する方法を説明する。

どうなればインストール完了と見なすか

4つのチェック、すべてターミナルで行う。

  1. docker ps の STATUS は Up、PORTS にマッピングがあり、IMAGE は指定した tag だ。
  2. curl -s http://127.0.0.1:5678/healthz 返す {"status":"ok"}。このエンドポイントはプロセスが生きていることだけを示す。
  3. docker exec n8n n8n --version 回 2.43.7、指定した tag と一致する。
  4. docker restart n8n、十数秒待ってからページを開くと、もうアカウント作成を求められないはずだ。

4番目が最も見落とされやすく、最も価値がある。これは一度に二つのことを同時に検証する:volume が正しく mount されている、データが本当に container の外にある。

容器里的 n8n 运行一个手动触发加编辑字段的工作流,输出三个字段
container 内でワークフローを作成して一度実行し、「三つのフィールドを書き込む」ノードが 1 item、三列を出力する。この画面が出れば、単に開けるウェブページではないことがわかる

このスクリーンショットを撮ったとき、ついでに container 内の .n8n、5.5 MB、上で述べたことと一致している。もしあなたの du -sh が数百 K しか出ないなら、大半のデータは container の書き込み可能レイヤーに書き込まれており、volume が mount されていない。

データは結局どのファイルにあるのか

volume を作成した後、ホスト側の実際の位置は Docker が決定する。次のコマンドで確認する:

docker volume inspect n8n_data
# [
#     {
#         "CreatedAt": "2026-11-02T09:28:41+08:00",
#         "Driver": "local",
#         "Mountpoint": "/var/lib/docker/volumes/n8n_data/_data",
#         "Name": "n8n_data",
#         "Scope": "local"
#     }
# ]

「Mountpoint」がホスト上の実際の位置である。私のこのマシンでは Docker のデータルートディレクトリを /data/dockerに移動しているので、表示されるのは /data/docker/volumes/n8n_data/_dataである;デフォルトインストールのマシンでは上記の /var/lib/docker/...になる。自分のマシンの出力を基準にすること。

container に入って見ると、n8n から見た姿はこうなる:

docker exec n8n ls -la /home/node/.n8n
# -rw-r--r-- 1 node node 1519616 Nov  2 09:29 database.sqlite
# -rw-r--r-- 1 node node   32768 Nov  2 09:38 database.sqlite-shm
# -rw-r--r-- 1 node node 4136512 Nov  2 09:37 database.sqlite-wal
# -rw-r--r-- 1 node node    7972 Nov  2 09:37 n8nEventLog-1.log
# -rw-r--r-- 1 node node     526 Nov  2 09:38 n8nEventLog.log

ワークフロー、実行記録、資格情報の暗号文はすべて database.sqlite の中にある。資格情報の復号に使う暗号化キーは同じディレクトリにあり、デフォルトでは config ファイルで、初回起動時に自動生成される。

したがって n8n のバックアップは2つだけである:このディレクトリと、バージョン番号。sqlite だけバックアップしてキーをバックアップしないと、別マシンで復元したとき資格情報がすべて文字化けする。

自分で指定したホストディレクトリ(例えば /data/n8n)に変更したい場合は、 -v n8n_data:/home/node/.n8n に置き換えれば -v /data/n8n:/home/node/.n8n それでいい。これが「バインドマウント」で、ディレクトリは自分で管理するからバックアップもより直感的だが、代償として権限は自分で解決しなければならない——次の落とし穴はそれだ。

実際によく遭遇する6つのミス

1. -v を忘れると、container を削除する=データベースを削除するのと同じ

2つの container で比較実験をした。同じマシン、同じ image: -v n8n_data:/home/node/.n8n が付いているほうは、再起動後に API が返す「初回セットアップを表示するか」が falseであり、 -v が付いていないもう一方は、同じ API が返すのが true——空のインスタンスに戻ってしまった。

プロセス全体でエラーも警告も出ない。ある日気づいたら workflow が消えていた、というだけだ。

判断方法:docker inspect n8nを実行し、上にスクロールして "Mounts" のセクションを探す。そこに "Destination": "/home/node/.n8n" が現れていれば mount されている;セクション全体が空なら危険だ。

2. ホストのディレクトリを mount すると EACCES が出る

bind mountを使いたいので、ディレクトリを作ってそのままmountすると:

Error: Failed to load command "start"
Error: EACCES: permission denied, open '/home/node/.n8n/config'

さっきまで正常に移行ログを出していたのに、突然ここで止まった。image内のn8nがrootではなく、uid 1000のユーザーだからだ node(docker exec n8n id 確認できる uid=1000(node))、そしてあなたが mkdir 作成したディレクトリの所有者はroot、755で、他のユーザーは書き込めない。

所有者を変更すればいい:

chown -R 1000:1000 /data/n8n

変更後に再実行すると、同じディレクトリ、同じコマンドで、200、正常に起動し、ファイルも実際にホスト側のディレクトリに書き込まれた。ホスト上でuid 1000が誰かは関係なく、container内では1000として認識される。

3. portが占有されている

docker: Error response from daemon: failed to set up container networking:
driver failed programming external connectivity on endpoint n8n
(...): failed to bind host port 0.0.0.0:5678/tcp: address already in use

つまりホストの5678がすでに誰かに使われていて、container内部とは一切関係ない。まず誰が使っているか確認する:

ss -ltnp 'sport = :5678'

よくあるのは以前のn8n containerがまだ動いている場合で、docker ps 確認できる。または古いcontainerを削除したが完全に消えていない場合、portを変えて先に起動するのが一番簡単だ。

4. IP + httpでアクセスすると、ログイン後にログインページに戻る

ページは開け、アカウントとパスワードも合っていて、ログインをクリックしてもエラーは出ないが、ページがログイン画面に戻る。パスワードが間違っているように見えるが、実際はcookieの問題だ。

n8nのログインcookieには Secure マークが付いており(N8N_SECURE_COOKIE デフォルトはそのまま true)、ブラウザは HTTPS の下でのみ保存を許可する。http でアクセスしても、サーバーは変わらず 200 を返すが、ブラウザはこの cookie をそのまま破棄するため、次のリクエストではまたログイン状態がなくなる。

二つの道:まともな方法は前に Nginx を一枚挟んで証明書を載せる;内網の一時デバッグなら、次を追加する -e N8N_SECURE_COOKIE=false、デバッグが終わったらこの行を忘れずに削除する。長期設定として扱わないこと——それはアカウントとパスワードを平文の経路上で走らせるのと同じだ。

5. ターミナルを閉じると、n8n も一緒に止まる

ドキュメントのあの docker run -it --rm に従って実行した場合、Ctrl+C で終了する。それはバックグラウンドサービスではなく、ターミナル内のフォアグラウンドプロセスだ。

补 -d 再実行する;すでに起動している場合は、docker start n8n でもそれを引き戻せるが、その container はすでに --rm が削除されている場合、再び docker runするしかない——データは volume 内にあり、まだ残っている。

6. latest を使っていて、ある日挙動が変わった

エラーもなく、アラートもなく、ただある日再起動後にノードのデフォルト値、UI、さらにはあるパラメータ名が変わった。原因は新しいバージョンを pull したことだ。

バージョン番号を固定し、アップグレードは正式な作業として行う:まず volume をバックアップし、次に tag を交換し、起動後に二つの重要な workflow を実行して結果を確認する。アップグレード自体に技術的な難しさはほとんどなく、面倒なのは「何が変わったか分からない」ことにある。

n8n に関係するいくつかのセキュリティ事項

5678 をそのまま公網に晒すな。n8n にはログインページがあるが、セルフホストアプリであり、ログイン以外に追加の防御はない。スキャナは毎日こうした port を探している。0.0.0.0 に置いて reverse proxy も HTTPS もなければ、家の鍵を玄関に掛けておくようなものだ。私がテストした時の書き方 -p 127.0.0.1:5678:5678 はすでに外側を塞いでいる。

docker グループは root と等しい。を / container に mount できる人間は、ホスト上のあらゆるファイルを変更できる。同僚に権限を渡す前にこれをよく考えろ。

volume は鍵として扱え。の中のあれは database.sqlite すべての credential の暗号文を保存しており、同じディレクトリに復号用の鍵がある。この二つを一緒に持ち出されたら、お前のすべての第三者アカウントの token は平文になる。backup をどこに置くかは、backup を取ることより重要だ。

コマンドラインに password を書くな。docker run -e DB_PASSWORD=xxx は docker inspect の出力に残り、誰が実行しても見られる。機密値を渡すなら env ファイルか、 _FILE 接尾辞の変数群を使え。

まとめ

四つの言葉を覚えれば動かせる:image はパッケージ、container は動いているパッケージ、volume はパッケージの外の土地、port は門牌番号だ。

n8n をインストールする際に本当に問題になるのは1点だけ:volume がマウントされていないこと。エラーも出ず、すぐには気づかない。気づいたときには workflow はもう消えている。だからインストール後に最初にやることは docker restart を一度実行し、データが残っているか確認する。

残りは慣れの問題。使い慣れると Docker の最大の利点は「クロスプラットフォーム」ではなく「トラブル時に一括削除してやり直せる」ことだと分かる——データは volume にあり、container はそもそもいつでも捨てられる。

前回の記事はn8n 起動エラーと port 競合の調べ方で、そちらは起動できない場合について書いた。シリーズ全体の目次はここにあり、障害系は別途トラブルシューティングページにまとめている。

参考資料

  • Install with Docker:公式の docker run コマンド、docker volume create、/home/node/.n8n volume の説明、および image 更新の手順
  • Docker Composeを使用してインストールする:compose版の設定、5678:5678 そのコメントには「唯一外部に公開すべきport」と書かれている
  • Deployment環境変数:N8N_PORT デフォルト5678、N8N_LISTEN_ADDRESS デフォルト ::、N8N_USER_FOLDER 与 N8N_ENCRYPTION_KEY
  • Security環境変数:N8N_SECURE_COOKIE デフォルト true、N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS デフォルト false
  • Docker volumes:volumeはホストマシンの /var/lib/docker/volumes/<名字>/_data、およびそれとbind mountの違い
  • n8nio/n8nのtag一覧:各バージョンごとに1つのtagがあり、image digestと圧縮サイズを確認できる
  • UbuntuにDocker Engineをインストールする:apt 公式リポジトリを使う完全手順。ワンクリックスクリプトを使いたくない場合はこの方法で。

最終更新:2026 年 11 月 2 日、n8n 2.43.7 を使用。

THE END