创建 Docker Compose 文件
首先,你需要创建并编辑 docker-compose.yml 文件。
进入项目目录:如果还没进入你之前创建的 n8n-article-system 目录,先导航过去。
bash:
cd ~/n8n-article-system
创建并编辑文件:在 Linux 中,我们通常使用命令行文本编辑器(如 nano)来创建和编辑文件。它的操作比较简单,适合新手。
bash:
nano docker-compose.yml
复制并粘贴配置内容:将下面这段完整的 docker-compose.yml 配置内容复制,然后回到 Ubuntu 命令行窗口,右键点击鼠标粘贴到 nano 编辑器中。
yml:
services:
n8n:
image: n8nio/n8n:latest
container_name: n8n-article-system
restart: unless-stopped
ports:
- "5678:5678"
environment:
- N8N_DEFAULT_BINARY_DATA_MODE=filesystem
- DB_SQLITE_DATABASE=/home/node/.n8n/database/n8n.sqlite
- TZ=Asia/Shanghai
volumes:
- ./database:/home/node/.n8n/database
- ./articles:/home/node/.n8n/articles

注:这里的 N8N_ENCRYPTION_KEY 用于加密敏感信息,在生产环境中务必将其修改为复杂的随机字符串
保存并退出 nano 编辑器:注意需要把光标移到到最后一行。
- 按下
Ctrl + O(Write Out) 来保存文件,按 Enter 确认文件名。 - 按下
Ctrl + X退出编辑器。
启动与管理容器
配置文件准备好后,启动和管理容器就很简单了
1.启动容器:在 docker-compose.yml 文件所在目录,执行以下命令来启动服务。-d 参数表示在后台运行
bash:
docker-compose up -d

首次运行会从 Docker Hub 下载 n8n 镜像,需要一点时间。
2.检查容器状态:启动后,使用以下命令确认容器是否正常运行。
bash:
docker-compose ps

如果状态 (State) 显示为 Up,就说明容器启动成功了。
3.查看实时日志:如果想查看容器的日志输出,可以使用:
bash:
docker-compose logs -f

按 Ctrl + C 可以退出日志查看。
常用的容器管理命令
掌握以下几个命令,你就能轻松管理这个容器了:
停止服务:这会停止容器,但不会删除它们
docker-compose stop
重新启动服务:
docker-compose restart
停止并删除容器:如果你想彻底停止并移除容器、网络等资源,可以使用:
docker-compose down
下次启动时,再次运行 docker-compose up -d 即可。
访问服务与文件
- 访问 n8n 网页界面:容器启动后,你可以在宿主机(Ubuntu)的浏览器中访问 http://localhost:5678 来使用 n8n。如果你的 Ubuntu 是纯命令行版本没有桌面环境,那么你可能需要通过网络 IP 来访问,或者暂时跳过这一步,专注于我们之前讨论的文章抓取工作流的搭建(这些也可以在命令行界面进行配置和管理)。
- 找到你生成的文件:根据 docker-compose.yml 中的配置,所有由 n8n 工作流生成的文章 Markdown 文件都会保存在 ~/n8n-article-system/articles/ 目录下。你可以在 Ubuntu 命令行中使用 ls ~/n8n-article-system/articles/ 命令来查看这些文件。
额外配置
配置备份策略
在 ~/n8n-article-system/ 目录下创建 backup.sh:(自动备份脚本)
nano backup.sh
内容:
#!/bin/bash
# 备份脚本 - 请将 /home/wang 替换为你的实际home路径
BACKUP_DIR="/home/wang/n8n-article-system/backups/$(date +%Y%m%d_%H%M%S)"
echo "📦 创建备份: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
# 备份数据库
if [ -d "/home/wang/n8n-article-system/database" ]; then
cp -r /home/wang/n8n-article-system/database "$BACKUP_DIR/" 2>/dev/null
echo "✅ 数据库备份完成"
else
echo "⚠️ 数据库目录不存在,跳过备份"
fi
# 备份文章
if [ -d "/home/wang/n8n-article-system/articles" ]; then
cp -r /home/wang/n8n-article-system/articles "$BACKUP_DIR/" 2>/dev/null
echo "✅ 文章备份完成"
else
echo "⚠️ 文章目录不存在,跳过备份"
fi
# 备份配置
if [ -d "/home/wang/n8n-article-system/config" ]; then
cp -r /home/wang/n8n-article-system/config "$BACKUP_DIR/" 2>/dev/null
echo "✅ 配置备份完成"
else
echo "⚠️ 配置目录不存在,跳过备份"
fi
# 创建压缩包
tar -czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR" 2>/dev/null
rm -rf "$BACKUP_DIR"
echo "🎉 备份完成: $BACKUP_DIR.tar.gz"
echo "📁 备份位置: /home/wang/n8n-article-system/backups/"

给脚本执行权限:
chmod +x backup.sh
配置日志轮转
同样在 ~/n8n-article-system/ 目录下创建 log-rotate.sh:
创建日志管理配置:
# 检查日志文件大小
du -sh logs/
# 如果日志太大,可以配置日志轮转
nano log-rotate.sh
内容:
#!/bin/bash
# 日志轮转脚本
LOG_DIR="/home/wang/n8n-article-system/logs"
BACKUP_DIR="/home/wang/n8n-article-system/log-backups"
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 检查日志目录是否存在
if [ ! -d "$LOG_DIR" ]; then
echo "⚠️ 日志目录不存在: $LOG_DIR"
exit 1
fi
# 备份并清理旧日志
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 如果有日志文件就备份
if ls "$LOG_DIR"/*.log 1> /dev/null 2>&1; then
# 创建备份
tar -czf "$BACKUP_DIR/logs_$TIMESTAMP.tar.gz" -C "$LOG_DIR" ./*.log 2>/dev/null
# 清空日志文件(不删除,只清空内容)
for logfile in "$LOG_DIR"/*.log; do
if [ -f "$logfile" ]; then
> "$logfile" # 清空文件内容
echo "🔄 清空日志文件: $(basename "$logfile")"
fi
done
echo "✅ 日志轮转完成"
echo "📦 备份位置: $BACKUP_DIR/logs_$TIMESTAMP.tar.gz"
else
echo "ℹ️ 没有找到日志文件,跳过轮转"
fi
# 删除30天前的旧备份
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete
echo "🗑️ 已清理30天前的旧备份"
测试脚本
# 测试备份脚本
./backup.sh
# 测试日志轮转脚本
./log-rotate.sh
# 查看备份文件
ls -la backups/
ls -la log-backups/

设置定时任务(可选)
如果你想要自动运行这些脚本,可以设置定时任务:lsl
# 编辑当前用户的crontab
crontab -e
添加以下内容:
# 每天凌晨2点执行备份
0 2 * * * /home/wang/n8n-article-system/backup.sh
# 每周一凌晨3点执行日志轮转
0 3 * * 1 /home/wang/n8n-article-system/log-rotate.sh
最终目录结构
现在的目录结构应该是:
~/n8n-article-system/
├── docker-compose.yml
├── backup.sh
├── log-rotate.sh
├── database/ # 自动生成
├── articles/ # 自动生成(工作流创建后)
├── backups/ # 备份文件
└── log-backups/ # 日志备份

MySQL 方案
更新 docker-compose.yml
在现有的 n8n 配置基础上添加 MySQL 服务:
services:
n8n:
image: n8nio/n8n
container_name: n8n-article-system
restart: unless-stopped
ports:
- "5678:5678"
environment:
- N8N_DEFAULT_BINARY_DATA_MODE=filesystem
- DB_TYPE=mysqldb
- DB_MYSQLDB_HOST=mysql
- DB_MYSQLDB_DATABASE=n8n
- DB_MYSQLDB_USER=n8n_user
- DB_MYSQLDB_PASSWORD=your_mysql_password
- TZ=Asia/Shanghai
- N8N_DEFAULT_TIMEZONE=Asia/Shanghai
- N8N_ENCRYPTION_KEY=change-this-to-a-random-secure-key
volumes:
- ./database:/home/node/.n8n/database
- ./articles:/home/node/.n8n/articles
- ./logs:/home/node/.n8n/logs
depends_on:
- mysql
networks:
- n8n-network
mysql:
image: mysql:8.0
container_name: n8n-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: your_root_password
MYSQL_DATABASE: n8n
MYSQL_USER: n8n_user
MYSQL_PASSWORD: your_mysql_password
volumes:
- mysql_data:/var/lib/mysql
- ./mysql/init:/docker-entrypoint-initdb.d
networks:
- n8n-network
volumes:
mysql_data:
networks:
n8n-network:
driver: bridge
创建必要的目录和初始化脚本
# 在 n8n-article-system 目录下创建 MySQL 相关目录
cd ~/n8n-article-system
mkdir -p mysql/init
# 创建数据库初始化脚本(可选)
nano mysql/init/01-create-schemas.sql
修改备份脚本支持 MySQL
更新你的 backup.sh 脚本:
#!/bin/bash
BACKUP_DIR="/home/wang/n8n-article-system/backups/$(date +%Y%m%d_%H%M%S)"
echo "📦 创建备份: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
# 备份 MySQL 数据库
echo "🗄️ 备份 MySQL 数据库..."
docker exec n8n-mysql mysqldump -u root -p"your_root_password" n8n > "$BACKUP_DIR/mysql-backup.sql" 2>/dev/null
if [ $? -eq 0 ]; then
echo "✅ MySQL 数据库备份完成"
else
echo "❌ MySQL 备份失败"
fi
# 备份文件数据
cp -r /home/wang/n8n-article-system/articles "$BACKUP_DIR/" 2>/dev/null && echo "✅ 文章备份完成"
cp -r /home/wang/n8n-article-system/logs "$BACKUP_DIR/" 2>/dev/null && echo "✅ 日志备份完成"
# 创建压缩包
tar -czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR" 2>/dev/null
rm -rf "$BACKUP_DIR"
echo "🎉 备份完成: $BACKUP_DIR.tar.gz"
部署步骤
停止现有服务(如果正在运行):
cd ~/n8n-article-system
docker-compose down
更新 docker-compose.yml:用上面的配置替换现有内容
修改密码:将 your_mysql_password 和 your_root_password 改为强密码
启动新服务:
docker-compose up -d
检查服务状态:
docker-compose ps
n8n 中 MySQL 节点的配置
在 n8n 工作流中使用 MySQL 节点时,配置如下:
- Host: mysql (Docker 容器名)
- Database: n8n
- User: n8n_user
- Password: your_mysql_password
- Port:
3306(默认)
常见问题
如果你运行之后,发现无法访问页面,但是容器又正常运行。

然后你运行docker logs n8n-article-system,返回结果我们只看最后几行
n8n ready on ::, port 5678
Migrations in progress, please do NOT stop the process.
Starting migration AddWorkflowVersionColumn1761047826451
Migration “AddWorkflowVersionColumn1761047826451” failed, error: Duplicate column name ‘versionCounter’
There was an error running database migrations
Duplicate column name ‘versionCounter’
Permissions 0644 for n8n settings file /home/node/.n8n/config are too wide. This is ignored for now, but in the future n8n will attempt to change the permissions automatically. To automatically enforce correct permissions now set N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true (recommended), or turn this check off set N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=false.然后我们可以发现n8n是准备在5678端口上的docker exec -it n8n-mysql mysql -u root -p”preluna” n8n,但是这里的问题是在于数据库文件重复创新的问题。(sqlite与mysql冲突),所以我们进入mysql容器,接着输入DESCRIBE workflow_entity;

输入 INSERT IGNORE INTO migrations (timestamp, name)
VALUES (1761047826451, ‘AddWorkflowVersionColumn1761047826451’);
输入exit退出
核心工作流配置
首先,创建一个新的工作流,并按照以下节点顺序进行配置。这套流程会引导你从WordPress获取文章,然后存入SQLite数据库。
| 节点类型 | 关键配置 | 主要用途 |
|---|---|---|
| Schedule Trigger | 规则:0 */6 * * * (每6小时) | 定时自动启动工作流 |
| HTTP Request | 方法:GET URL:https://你的网站域名/wp-json/wp/v2/posts 认证:Basic Auth | 获取WordPress文章列表 |
| Code | 模式:Run once for all items 解析JSON,提取所需字段 | 清洗和格式化API返回的数据 |
| SQLite | 操作:Execute Query 创建articles表并插入数据 | 将处理后的文章数据存入数据库 |
下面是每个节点的详细配置说明
配置 Schedule Trigger 节点
这个节点负责按计划启动整个流程。
- 在节点参数中,将Trigger Times的规则(Rule)设置为 0 */6 * * *,这代表每6小时自动运行一次。您可以根据需要调整频率。
配置 HTTP Request 节点
这是与WordPress站点通信的关键节点
- 方法 (Method):选择
GET。 - URL:填写你的WordPress文章API端点:https://你的网站域名/wp-json/wp/v2/posts。你可以在URL中添加参数,例如 ?per_page=5 来限制首次测试的文章数量。
- 认证 (Authentication):选择 Generic Credential 类型下的 Basic Auth。


配置 Code 节点
WordPress API返回的数据结构比较复杂,这个节点用于提取我们需要的信息。
- 将模式 (Mode) 设置为 Run once for all items。
- 在代码框中输入以下JavaScript代码,它将原始数据转换为更结构化的格式
// 从上游HTTP Request节点读取原始文章列表数据
const rawArticles = $input.all();
// 对每篇文章进行映射,提取我们关心的字段
const articles = rawArticles.map(article => {
return {
wp_id: article.json.id,
title: article.json.title.rendered,
slug: article.json.slug,
url: article.json.link,
status: article.json.status,
content: article.json.content.rendered,
modified: article.json.modified,
// 计算内容哈希,用于后续判断文章是否更新
content_hash: Buffer.from(article.json.content.rendered).toString('base64').substring(0, 64)
};
});
// 将处理好的文章数组返回给下一个节点
return articles;
MySQL初始化节点配置
凭证配置:
- Connection Type: MySQL
- Host:
mysql⭐(必须使用容器名) - Database:
n8n(n8n 系统数据库) - User:
n8n_user - Password: 你的MySQL密码
- Port:
3306
数据库分离(可选)
如果你想像我一样进行数据库分离的话。
步骤1:创建正确的目录结构
cd ~/n8n-article-system
mkdir -p mysql-init
# 创建初始化脚本
nano mysql-init/01-create-article-system.sql
步骤2:编写初始化脚本内容
-- 文件: 01-create-article-system.sql
-- 创建文章系统数据库
CREATE DATABASE IF NOT EXISTS article_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 授予 n8n_user 用户权限(用户已在环境变量中创建)
GRANT ALL PRIVILEGES ON article_system.* TO 'n8n_user'@'%';
-- 刷新权限
FLUSH PRIVILEGES;
-- 可选:验证创建成功
SELECT 'article_system 数据库初始化完成' as status;
步骤3:验证脚本语法
# 验证 SQL 语法(可选)
docker exec n8n-mysql mysql -u root -p你的密码 -e "SOURCE /docker-entrypoint-initdb.d/01-create-article-system.sql;" 2>&1
步骤4:确保 Docker 配置正确
mysql:
image: mysql:8.0
container_name: n8n-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: 你的root密码
MYSQL_DATABASE: n8n
MYSQL_USER: n8n_user
MYSQL_PASSWORD: 你的MySQL密码
volumes:
- mysql_data:/var/lib/mysql
- ./mysql-init:/docker-entrypoint-initdb.d # 关键挂载点
networks:
- n8n-network
重启服务并查看日志
docker-compose down
docker-compose up -d mysql
docker-compose logs mysql | grep -A 10 -B 10 "Initializing database"
验证数据库创建
# 等待 MySQL 完全启动后检查数据库
sleep 10
docker exec n8n-mysql mysql -u n8n_user -p你的密码 -e "SHOW DATABASES;"
应该看到输出中包含:
+--------------------+
| Database |
+--------------------+
| article_system | ⭐ 这个就是初始化脚本创建的
| information_schema |
| n8n |
| performance_schema |
+--------------------+

进入容器检查文件
# 检查初始化脚本是否正确挂载
docker exec n8n-mysql ls -la /docker-entrypoint-initdb.d/
# 应该看到:
# -rw-r--r-- 1 1000 1000 1234 Jan 15 10:30 01-create-article-system.sql

同理,你的凭证也应该看到图片这样的修改,只要将数据库的名称换成你自己的名称就行了。


按照图片中的sql进行连接测试。
完整的表结构设计
1. 创建文章表
-- 创建文章主表
CREATE TABLE IF NOT EXISTS articles (
id INT AUTO_INCREMENT PRIMARY KEY,
wp_id INT UNIQUE NOT NULL, -- WordPress 文章 ID
title TEXT NOT NULL, -- 文章标题
slug VARCHAR(200), -- URL 别名
url VARCHAR(500) NOT NULL, -- 完整文章 URL
status VARCHAR(20) DEFAULT 'publish', -- 文章状态
content_hash VARCHAR(64), -- 内容哈希值(用于检测变更)
md_file_path TEXT, -- 生成的 MD 文件路径
is_deleted TINYINT(1) DEFAULT 0, -- 标记是否被删除
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 记录创建时间
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 最后更新时间
last_sync TIMESTAMP NULL DEFAULT NULL, -- 最后同步时间
last_modified TIMESTAMP NULL DEFAULT NULL, -- 文章最后修改时间(从 WordPress 获取)
-- 索引优化
INDEX idx_wp_id (wp_id),
INDEX idx_updated (updated_at),
INDEX idx_deleted (is_deleted),
INDEX idx_status (status),
INDEX idx_last_modified (last_modified),
INDEX idx_content_hash (content_hash)
);
2. 创建同步历史表
-- 创建文章版本表(可选,用于详细追踪内容变化)
CREATE TABLE IF NOT EXISTS article_versions (
id INT AUTO_INCREMENT PRIMARY KEY,
wp_id INT NOT NULL, -- WordPress 文章 ID
title TEXT, -- 文章标题
content_hash VARCHAR(64), -- 内容哈希
version INT DEFAULT 1, -- 版本号
change_type VARCHAR(20), -- 变更类型:new, update, minor_edit
captured_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 捕获时间
-- 索引优化
INDEX idx_wp_id_version (wp_id, version),
INDEX idx_captured (captured_at),
FOREIGN KEY (wp_id) REFERENCES articles(wp_id) ON DELETE CASCADE
);
3. 创建文章版本表(用于追踪内容变化)
-- 创建文章版本表(可选,用于详细追踪内容变化)
CREATE TABLE IF NOT EXISTS article_versions (
id INT AUTO_INCREMENT PRIMARY KEY,
wp_id INT NOT NULL, -- WordPress 文章 ID
title TEXT, -- 文章标题
content_hash VARCHAR(64), -- 内容哈希
version INT DEFAULT 1, -- 版本号
change_type VARCHAR(20), -- 变更类型:new, update, minor_edit
captured_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 捕获时间
-- 索引优化
INDEX idx_wp_id_version (wp_id, version),
INDEX idx_captured (captured_at),
FOREIGN KEY (wp_id) REFERENCES articles(wp_id) ON DELETE CASCADE
);
在 n8n 工作流中执行 SQL
完整的初始化 SQL(可重复执行)
在 n8n 的 MySQL 节点中使用这个完整的 SQL:
-- 初始化文章系统表结构(幂等操作)
USE article_system;
-- 创建文章主表
CREATE TABLE IF NOT EXISTS articles (
id INT AUTO_INCREMENT PRIMARY KEY,
wp_id INT UNIQUE NOT NULL,
title TEXT NOT NULL,
slug VARCHAR(200),
url VARCHAR(500) NOT NULL,
status VARCHAR(20) DEFAULT 'publish',
content_hash VARCHAR(64),
md_file_path TEXT,
is_deleted TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
last_sync TIMESTAMP NULL DEFAULT NULL,
last_modified TIMESTAMP NULL DEFAULT NULL,
INDEX idx_wp_id (wp_id),
INDEX idx_updated (updated_at),
INDEX idx_deleted (is_deleted),
INDEX idx_status (status),
INDEX idx_last_modified (last_modified),
INDEX idx_content_hash (content_hash)
);
-- 创建同步历史表
CREATE TABLE IF NOT EXISTS sync_history (
id INT AUTO_INCREMENT PRIMARY KEY,
sync_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
new_articles INT DEFAULT 0,
updated_articles INT DEFAULT 0,
deleted_articles INT DEFAULT 0,
sync_duration INT,
success TINYINT(1) DEFAULT 1,
error_message TEXT,
articles_checked INT DEFAULT 0,
INDEX idx_timestamp (sync_timestamp),
INDEX idx_success (success)
);
-- 创建文章版本表(可选)
CREATE TABLE IF NOT EXISTS article_versions (
id INT AUTO_INCREMENT PRIMARY KEY,
wp_id INT NOT NULL,
title TEXT,
content_hash VARCHAR(64),
version INT DEFAULT 1,
change_type VARCHAR(20),
captured_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_wp_id_version (wp_id, version),
INDEX idx_captured (captured_at)
);
-- 插入初始同步记录
INSERT IGNORE INTO sync_history (id, new_articles, updated_articles, deleted_articles, sync_duration, articles_checked)
VALUES (1, 0, 0, 0, 0, 0);
SELECT '数据库表结构初始化完成' as status;
完整的工作流设计
工作流节点结构:
[手动触发]
→ [初始化数据库表]
→ [获取WordPress文章列表]
→ [处理文章数据]
→ [检测变更]
→ [提取文章内容]
→ [生成MD文件]
→ [更新数据库记录]
→ [记录同步历史]
1. 获取文章列表节点(HTTP Request)
调用 WordPress REST API:
// URL: https://你的博客.com/wp-json/wp/v2/posts
// 参数: ?per_page=100&orderby=modified&order=desc
2. 处理文章数据节点(Code)
// 计算内容哈希和处理数据
const crypto = require('crypto');
function calculateHash(content) {
return crypto.createHash('md5').update(content).digest('hex');
}
const articles = $input.all().map(article => ({
wp_id: article.id,
title: article.title.rendered,
slug: article.slug,
url: article.link,
status: article.status,
content_hash: calculateHash(article.content.rendered),
last_modified: article.modified,
content: article.content.rendered,
excerpt: article.excerpt.rendered
}));
return articles;
3. 检测变更节点(Code + MySQL)
// 获取现有文章记录进行比对
const currentArticles = $input.all();
// 这里需要从数据库查询现有文章记录进行比对
// 返回新增、更新、删除的文章列表
4. 记录同步历史节点(MySQL)
-- 插入同步记录
INSERT INTO sync_history (new_articles, updated_articles, deleted_articles, sync_duration, articles_checked, success)
VALUES (?, ?, ?, ?, ?, 1);
数据持久化保证
唉,主播主播,如果我这么一个流程执行完之后,我这个数据能不能进行长久化保存?如果我的这个容器进行了重启,那是不是我这些数据都清零了?哎兄弟不会的,你的数据会持久化保存,即使容器重启也不会丢失数据。让我详细解释数据持久化的机制:
数据持久化架构:
当前的数据存储设计:容器内部 (易失) ← 卷挂载 → 宿主机 (持久化)
持久化配置分析
n8n 服务的卷配置:
n8n:
volumes:
- ./database:/home/node/.n8n/database # 宿主机目录映射
- ./articles:/home/node/.n8n/articles # 宿主机目录映射
- ./logs:/home/node/.n8n/logs # 宿主机目录映射
mysql 服务的卷配置:
mysql:
volumes:
- mysql_data:/var/lib/mysql # Docker 命名卷
- ./mysql/init:/docker-entrypoint-initdb.d # 宿主机目录映射
卷声明:
volumes:
mysql_data: # Docker 命名卷声明
查找 mysql_data 卷的位置
方法1:查看所有 Docker 卷
# 列出所有 Docker 卷
docker volume ls

方法2:查看具体卷信息
# 查看 mysql_data 卷的详细信息
docker volume inspect n8n-article-system_mysql_data
# 或者使用项目名称前缀
docker volume inspect $(docker volume ls -q | grep mysql_data)

方法3:检查卷的实际存储路径
# 查看卷在宿主机上的实际存储路径
docker volume inspect n8n-article-system_mysql_data | grep Mountpoint

理解两种卷类型的区别
| 卷类型 | 示例 | 存储位置 | 可见性 | 管理方式 |
|---|---|---|---|---|
| 管理方式 | ./database:/path | 项目目录内 | 直接可见和访问 | 手动管理 |
| Docker 命名卷 | mysql_data:/path | Docker 存储区域 | 需要通过 Docker 命令访问 | Docker 自动管理 |
项目目录结构
~/n8n-article-system/
├── docker-compose.yml
├── database/ # n8n 的 SQLite 数据(如果使用)
├── articles/ # 生成的 MD 文件
├── logs/ # 日志文件
├── mysql/
│ └── init/ # 初始化脚本
└── (mysql_data 卷在 Docker 管理区域,不在此目录)
验证卷配置是否工作
检查卷是否正常挂载:
# 检查 MySQL 容器内的卷挂载
docker exec n8n-mysql ls -la /var/lib/mysql
# 检查初始化脚本是否挂载
docker exec n8n-mysql ls -la /docker-entrypoint-initdb.d/
验证数据持久化:
# 创建测试数据
docker exec n8n-mysql mysql -u n8n_user -ppreluna -e "CREATE DATABASE IF NOT EXISTS test_persistence;"
# 重启服务
docker-compose restart
# 检查数据是否还在
docker exec n8n-mysql mysql -u n8n_user -ppreluna -e "SHOW DATABASES;" | grep test_persistence
如何访问 mysql_data 卷的数据
虽然 mysql_data 不在项目目录中,但你仍然可以访问:
备份 mysql_data 卷:
# 备份整个 MySQL 数据
docker run --rm -v n8n-article-system_mysql_data:/source -v $(pwd):/backup alpine tar czf /backup/mysql-backup.tar.gz -C /source .
查看卷内容:
# 临时挂载卷查看内容
docker run --rm -v n8n-article-system_mysql_data:/data alpine ls -la /data


