n8n 搬家不丢数据:Windows 和 macOS 如何迁移 Docker 数据卷
适用场景:你原本在 Windows 或 macOS 本地部署了 n8n,后来发现新闻检索、汇率监控、每日热点整理、Webhook 接收等任务需要机器长时间运行,于是准备把 n8n 搬到另一台长期在线的电脑、NAS、Linux 服务器或云主机。本文也适用于换电脑、重装 Docker、从本地迁移到服务器,以及把一套已经运行稳定的 n8n 环境完整复制到新设备。

先说结论:真正要搬的不是容器,而是数据卷
很多人第一次迁移 n8n,会把注意力放在“怎么把容器复制过去”。但容器更像是临时搭好的办公室,里面的桌椅可以随时重新摆;真正重要的是办公室里的文件柜。n8n 的工作流、凭据、执行记录、加密密钥和部分实例设置,都保存在持久化数据目录里,而不是保存在容器本身。
官方 Docker 示例会把 Docker 卷 n8n_data 挂载到容器内的 /home/node/.n8n。只要这个目录里的内容完整,并且新设备用正确的方式挂载回来,工作流就能继续出现。[1] 如果只复制镜像或只重新创建一个叫 n8n 的容器,通常只能得到一个“全新的 n8n”,原来的工作流和凭据不会自动回来。

你需要迁移哪些东西
最稳妥的迁移包通常包含四部分:n8n 数据卷、Docker Compose 文件或原始启动命令、.env 环境变量文件,以及你自己挂载的本地文件目录。如果你使用 PostgreSQL,还要额外迁移 PostgreSQL 数据库卷或执行数据库备份;如果只使用 n8n 默认的 SQLite,通常重点就是 /home/node/.n8n 对应的数据卷。
需要特别注意的是,凭据数据往往经过加密。如果新设备只恢复了数据库,却没有保留原来的 N8N_ENCRYPTION_KEY,可能会出现“工作流还在,但凭据无法使用”的情况。因此迁移时不要只看工作流数量,还要确认原来的加密密钥和环境变量也一并保留。[2]
| 迁移内容 | 是否建议迁移 | 作用 |
|---|---|---|
| n8n 数据卷 | 必须 | 保存工作流、凭据、数据库、密钥和实例数据 |
compose.yaml |
强烈建议 | 记录容器、端口、卷和环境变量配置 |
.env |
强烈建议 | 保存域名、时区、数据库等运行参数;注意保护密码 |
local-files |
视情况 | 保存工作流读写的本地文件 |
| PostgreSQL 数据 | 使用 PostgreSQL 时必须 | 保存工作流和凭据等数据库内容 |
| Docker 镜像 | 不一定 | 新设备可以重新拉取相同版本镜像 |

第一步:先让旧设备处于安全状态
迁移前不要让 n8n 一边运行一边打包数据。你可以把它想象成搬家时不能让家人继续在房间里写文件,否则刚刚装箱的文件又会被改动,最后会出现新旧两份内容不一致。先停止 n8n 容器,再进行导出。
如果你使用 Docker Compose,在旧设备的项目目录执行:
# Windows PowerShell 或 macOS Terminal 都可以使用
cd 你的-n8n-compose-目录
docker compose stop n8n
如果你不是用 Compose,而是直接 docker run 启动,可以先找出容器:
docker ps -a --filter "name=n8n"
然后停止它:
docker stop n8n
如果你的容器名字不是 n8n,就把命令里的 n8n 换成实际容器名。注意:容器名和数据卷名不是一回事。容器名可能叫 n8n-main,数据卷可能叫 n8n-compose_n8n_data,不能想当然地直接输入。

Windows:先找到 n8n 容器叫什么
在 Windows 上打开 PowerShell。不要使用普通 CMD 也可以,但本文命令默认使用 PowerShell 语法。先列出所有容器:
docker ps -a
如果容器很多,可以筛选名称中包含 n8n 的容器:
docker ps -a --filter "name=n8n"
你会看到类似这样的结果:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 docker.n8n.io/n8nio/n8n "tini -- /docker-ent…" 8 days ago Up 2 hours 0.0.0.0:5678->5678/tcp n8n
这里最右侧的 NAMES 才是容器名。后面检查挂载关系时,可以使用这个名字:
docker inspect n8n
为了只查看挂载信息,可以使用 PowerShell 过滤:
docker inspect n8n --format '{{json .Mounts}}'
如果想让结果更容易阅读:
docker inspect n8n --format '{{range .Mounts}}{{println "类型:" .Type "名称:" .Name "宿主路径:" .Source "容器路径:" .Destination}}{{end}}'
你需要重点寻找这一行:
类型: volume 名称: n8n_data 宿主路径: /var/lib/docker/volumes/n8n_data/_data 容器路径: /home/node/.n8n
在 Windows Docker Desktop 中,宿主路径有时显示的是 Docker 的 Linux 虚拟环境路径,不一定能直接在资源管理器里打开。这是正常现象,因为 Docker Desktop 的 Linux 容器运行在内部虚拟机或 WSL2 环境中。不要直接去猜 C:\ProgramData\Docker 下哪个文件夹是 n8n,最可靠的方式是通过 Docker 命令导出卷内容。

Windows:忘记数据卷名字时怎么查询
先列出所有 Docker 数据卷:
docker volume ls
如果卷很多,可以筛选名称中包含 n8n 的卷:
docker volume ls --filter "name=n8n"
你可能看到几种不同的结果:
DRIVER VOLUME NAME
local n8n_data
local n8n-compose_n8n_data
local someproject_n8n_data
如果你使用 Docker Compose,Docker 往往会自动给卷名前面加项目名,所以你在 Compose 里写的是 n8n_data,实际名称可能变成 n8n-compose_n8n_data。此时不要凭感觉选择,而是逐个检查:
docker volume inspect n8n_data
docker volume inspect n8n-compose_n8n_data
更好的方式是反过来从容器挂载关系中确认:
docker inspect n8n --format '{{range .Mounts}}{{println .Type .Name .Destination}}{{end}}'
只要看到目标路径是 /home/node/.n8n,它对应的 Name 就是 n8n 的核心数据卷。

Windows:直接查看数据卷里面有没有 n8n 数据
不要直接进入 Docker Desktop 的内部磁盘文件夹查看。我们可以临时启动一个轻量容器,把目标数据卷挂载进去,然后列出文件。这个临时容器不会修改你的 n8n 数据:
docker run --rm -it `
-v n8n_data:/data `
alpine:latest `
sh -c "find /data -maxdepth 2 -type f | sort | head -80"
如果你的实际卷名是 n8n-compose_n8n_data,请换成:
docker run --rm -it `
-v n8n-compose_n8n_data:/data `
alpine:latest `
sh -c "find /data -maxdepth 2 -type f | sort | head -80"
正常情况下,里面会看到类似 .n8n 目录中的数据库、配置或密钥文件。不同 n8n 版本的文件数量会不同,不要只依赖某一个文件名判断;更重要的是确认卷确实挂载到了 /home/node/.n8n。

推荐方案:用临时容器把 Docker 卷打包成 tar.gz
这是跨 Windows、macOS、Linux 最稳妥的迁移方法。它不要求你知道 Docker Desktop 内部卷的真实磁盘路径,也不依赖你能否直接访问 WSL2 或 Docker Desktop 虚拟机。Docker 官方也提供了通过临时容器挂载卷并使用归档工具备份、恢复卷的思路。[3]
先在旧设备准备一个存放备份的目录。Windows 例如:
New-Item -ItemType Directory -Force -Path "$HOME\n8n-migration"
macOS 例如:
mkdir -p ~/n8n-migration
Windows 下执行导出。注意 PowerShell 的路径写法:
docker run --rm `
-v n8n_data:/volume `
-v "$HOME\n8n-migration:/backup" `
alpine:latest `
sh -c "cd /volume && tar czf /backup/n8n_data_backup.tar.gz ."
macOS 下执行导出:
docker run --rm \
-v n8n_data:/volume \
-v "$HOME/n8n-migration:/backup" \
alpine:latest \
sh -c 'cd /volume && tar czf /backup/n8n_data_backup.tar.gz .'
如果你的卷名不是 n8n_data,把命令中的 n8n_data 替换成实际名称。导出结束后检查文件是否存在以及大小是否合理:
Get-Item "$HOME\n8n-migration\n8n_data_backup.tar.gz"
macOS:
ls -lh ~/n8n-migration/n8n_data_backup.tar.gz
如果文件只有几 KB,而你的 n8n 已经运行很久,建议先不要迁移,重新确认卷名和挂载路径。一个空卷或选错卷,是迁移失败最常见的原因之一。

不要忘记保存 Compose 文件和环境变量
数据卷只保存数据,不一定保存你启动 n8n 时使用的所有运行参数。请把旧设备上的 compose.yaml、docker-compose.yml、.env 和自定义的 local-files 目录一起复制到迁移包中。
可以先在项目目录执行:
dir
确认至少有类似这些文件:
compose.yaml
.env
local-files\
如果使用的是 PowerShell,可以把 Compose 配置复制到备份目录:
Copy-Item .\compose.yaml "$HOME\n8n-migration\" -Force
Copy-Item .\.env "$HOME\n8n-migration\" -Force
Copy-Item .\local-files "$HOME\n8n-migration\local-files" -Recurse -Force
macOS:
cp compose.yaml .env ~/n8n-migration/
cp -R local-files ~/n8n-migration/
.env 里可能包含数据库密码、Webhook 密钥或加密密钥,不能公开上传到 GitHub,也不要发给别人。迁移完成后,如果你怀疑文件曾经泄露,应及时更换相关凭据。

把备份包传到新设备
你可以使用移动硬盘、局域网共享、SCP、SFTP、pCloud、WebDAV 或其他可靠方式传输。对于包含 n8n 凭据的数据包,建议使用加密压缩包或加密磁盘,不要把它放在公开链接上。
如果新设备是 Linux 云服务器,可以在旧设备上使用 SCP:
scp "$HOME\n8n-migration\n8n_data_backup.tar.gz" username@你的服务器IP:/home/username/n8n-migration/
scp "$HOME\n8n-migration\compose.yaml" username@你的服务器IP:/home/username/n8n-migration/
scp "$HOME\n8n-migration\.env" username@你的服务器IP:/home/username/n8n-migration/
如果新设备也是 Windows 或 macOS,直接复制整个 n8n-migration 文件夹即可。传输完成后,最好在两台设备上分别计算哈希值:
Windows:
Get-FileHash "$HOME\n8n-migration\n8n_data_backup.tar.gz" -Algorithm SHA256
macOS 或 Linux:
shasum -a 256 ~/n8n-migration/n8n_data_backup.tar.gz
两边结果一致,说明传输过程中文件内容没有变化。

新设备:先创建同名的空数据卷
到新设备后,不要马上启动 n8n。先创建目标卷:
docker volume create n8n_data
确认它存在:
docker volume ls --filter "name=n8n_data"
如果 Compose 项目会自动加前缀,也可以让 Compose 创建卷,但建议在导入前明确知道真实卷名。对于本文的命令,统一使用 n8n_data,这样最不容易混乱。

新设备:把 tar.gz 恢复到数据卷
假设迁移包放在新设备的 n8n-migration 目录中。Windows PowerShell 使用下面的命令:
docker run --rm `
-v n8n_data:/volume `
-v "$HOME\n8n-migration:/backup" `
alpine:latest `
sh -c "cd /volume && tar xzf /backup/n8n_data_backup.tar.gz"
macOS 或 Linux 使用:
docker run --rm \
-v n8n_data:/volume \
-v "$HOME/n8n-migration:/backup" \
alpine:latest \
sh -c 'cd /volume && tar xzf /backup/n8n_data_backup.tar.gz'
恢复完成后,检查卷里是否已经有文件:
docker run --rm -it `
-v n8n_data:/data `
alpine:latest `
sh -c "find /data -maxdepth 2 -type f | sort | head -80"
如果恢复命令没有报错,但检查出来是空的,通常是备份包路径写错、挂载到了错误卷,或打包时使用了错误的数据卷。

新设备:让 n8n 使用恢复后的卷
如果你使用 Docker Compose,确认 compose.yaml 中的挂载关系仍然是:
services:
n8n:
image: docker.n8n.io/n8nio/n8n
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
external: true
external: true 的意思是:这个卷已经由你手动创建和恢复,Compose 不要再创建一份同名但内容为空的新卷。如果你的 Compose 项目使用自动生成的项目卷名,就必须按实际名称调整配置,否则 n8n 可能启动成功,但看到的是空白新实例。
启动前先检查配置:
docker compose config
确认没有错误后启动:
docker compose up -d
然后查看日志:
docker compose logs -f n8n
macOS 和 Linux 使用相同的 Docker Compose 命令。看到 n8n 正常启动后,再打开浏览器登录。

恢复后如何判断迁移成功
不要只看“网页能打开”,要做一套完整检查。首先确认原来的工作流数量和名称是否存在;其次打开一个使用凭据的节点,确认凭据仍然能正常选择;然后手动执行一个不会产生副作用的测试工作流;最后检查定时任务、Webhook 地址、时区和本地文件路径。
如果工作流都出现,但凭据全部报错,优先检查 N8N_ENCRYPTION_KEY 是否和旧设备一致。若你使用的是 PostgreSQL,要确认新设备连接的是恢复后的 PostgreSQL,而不是新建的空数据库。若工作流能运行但文件节点报错,检查 local-files 是否一起迁移,并且容器内路径仍然是 /files。
# 查看 n8n 容器实际挂载关系
docker inspect n8n --format '{{range .Mounts}}{{println .Type .Name .Source .Destination}}{{end}}'
# 查看容器环境变量中是否配置了时区和加密密钥名称
# 不要把实际密钥值复制到公开地方
docker inspect n8n --format '{{range .Config.Env}}{{println .}}{{end}}' | Select-String 'N8N_|TZ|DB_'

Windows 和 macOS 的差异到底在哪里
迁移逻辑其实是一样的:停止 n8n、确认容器和卷、导出卷、传输、创建新卷、导入、重新挂载、验证。差异主要在 Docker Desktop 的底层实现和命令行路径写法。
Windows Docker Desktop 的 Linux 容器数据通常位于 Docker Desktop 管理的 WSL2 或虚拟磁盘中,不建议手工钻进内部磁盘复制某个目录。Docker 官方提供的完整 Docker Desktop 备份路径包括 %LOCALAPPDATA%\Docker\wsl\data\docker_data.vhdx,但这适合备份整个 Docker Desktop 环境;如果你只迁移 n8n,本文的“临时容器 + tar.gz”方法更轻、更容易跨设备恢复。[3]
macOS Docker Desktop 同样把 Linux 容器数据放在 Docker 管理的虚拟磁盘中。官方完整备份路径是 ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw,但这适合整体迁移 Docker Desktop。只迁移 n8n 时,仍然建议导出 named volume,而不是直接复制 Docker.raw。[3]

如果你使用的是绑定目录,而不是 named volume
有些人安装 n8n 时不是写 n8n_data:/home/node/.n8n,而是写了类似下面的绑定目录:
volumes:
- ./n8n-data:/home/node/.n8n
这时 docker inspect 显示的类型会是 bind,而不是 volume。数据就在 Compose 文件旁边的 n8n-data 文件夹里,迁移时直接复制这个文件夹即可:
Copy-Item .\n8n-data "$HOME\n8n-migration\n8n-data" -Recurse -Force
macOS:
cp -R ./n8n-data ~/n8n-migration/
在新设备上把同一个目录放回 Compose 文件对应的位置,再执行 docker compose up -d。不要把 named volume 的命令和 bind mount 的命令混用;一个是 Docker 管理的卷,一个是宿主机上的真实文件夹。

常见问题一:迁移后工作流还在,但凭据不能用
这通常不是卷没有恢复,而是加密密钥不一致。n8n 的凭据不会以明文形式简单存储;如果新容器使用了不同的加密密钥,它无法正确解密旧凭据。解决方法是恢复旧的 N8N_ENCRYPTION_KEY 环境变量,或者使用旧 Compose 和 .env 配置启动。
不要在文章、截图或公开仓库中展示真实密钥。如果旧密钥已经泄露,应该先评估影响并轮换所有相关 API Key,然后在新环境中重新配置 n8n 凭据。

常见问题二:迁移后出现全新的空白 n8n
最常见原因是 n8n 挂载到了另一个空卷。你可以检查:
docker inspect n8n --format '{{range .Mounts}}{{println "卷名:" .Name "容器路径:" .Destination}}{{end}}'
如果 /home/node/.n8n 对应的卷名不是你刚刚恢复的 n8n_data,就说明 Compose 使用了另一份卷。检查 Compose 项目名前缀、卷名和 external: true 配置,确保容器挂载的是恢复后的卷。

常见问题三:容器能启动,但网页打不开
数据卷恢复和网络访问是两件事。先看容器是否运行:
docker ps
再看端口映射:
docker port n8n
如果你想在本机直接访问,通常需要看到类似 5678/tcp -> 0.0.0.0:5678 的映射。如果你使用反向代理,n8n 可能只绑定到 127.0.0.1:5678,这时需要从域名和 HTTPS 入口访问,而不是直接访问服务器 IP。
docker compose logs --tail=100 n8n

常见问题四:定时任务时间不对
迁移后定时任务提前或延迟,通常是时区环境变量不同。检查旧设备和新设备的 TZ、GENERIC_TIMEZONE,例如:
environment:
- TZ=Asia/Shanghai
- GENERIC_TIMEZONE=Asia/Shanghai
TZ 影响系统时间相关行为,GENERIC_TIMEZONE 会影响 Schedule Trigger 等时间调度节点。n8n 官方 Docker 示例也建议显式设置这两个时区变量。[2]

常见问题五:Webhook 地址变了
如果 n8n 从本地迁移到服务器,Webhook 地址通常会发生变化。工作流里的 Webhook 节点本身可能仍然存在,但第三方服务保存的回调地址需要重新更新。迁移到域名后,要检查 N8N_HOST、N8N_PROTOCOL、WEBHOOK_URL 和反向代理配置。
本地测试可以使用 http://localhost:5678 ,生产环境则应该使用 HTTPS 域名,例如:
WEBHOOK_URL=https://n8n.example.com/
N8N_PROTOCOL=https
N8N_HOST=n8n.example.com
n8n 官方 Compose 示例也使用域名、HTTPS 和反向代理来提供生产访问 。[4]

一套可以反复使用的迁移脚本思路
如果你以后经常迁移,可以把步骤固定成“停机—确认—导出—校验—传输—恢复—验证”七个动作。不要把所有命令写成一个没有检查的长脚本,因为一旦卷名写错,脚本仍然可能成功执行,但打包出来的是空数据。
最重要的判断点是:导出前确认挂载路径;导出后确认压缩包大小;传输后确认 SHA-256;恢复后确认卷内文件;启动后确认容器挂载关系。每一步都检查,迁移就不会变成“启动了一个全新的 n8n”。

最后总结:什么时候应该迁移 n8n
当你只是在本地学习 n8n,电脑开机时间不长,本地部署非常方便;但当你开始做每日新闻检索、汇率监控、内容汇总、Webhook 接收或夜间自动运行,长期让个人电脑保持开机就会变得不稳定。此时可以把 n8n 迁移到一台长期在线的设备,例如 NAS、Linux 小主机、云服务器或 Oracle Cloud 主机。
迁移的核心不是“把 n8n 重新安装一遍”,而是把原来的持久化数据卷完整搬到新设备,再用相同的挂载路径、环境变量和加密密钥启动。只要记住这句话:容器可以重建,数据卷不能丢;镜像可以重新拉取,加密密钥不能忘记。

参考资料
[1]: https://docs.docker.com/engine/storage/volumes/ Docker 官方:Volumes[2]: https://docs.n8n.io/deploy/host-n8n/install-options/install-with-docker n8n 官方:Install with Docker[3]: https://docs.docker.com/desktop/settings-and-maintenance/backup-and-restore/ Docker 官方:How to back up and restore your Docker Desktop data[4]: https://docs.n8n.io/deploy/host-n8n/install-options/use-a-cloud-provider/use-docker-compose n8n 官方:Use Docker Compose