378 lines
13 KiB
Markdown
378 lines
13 KiB
Markdown
#nas #minio #zipline #docker #synology #n8n #image
|
||
```table-of-contents
|
||
```
|
||
|
||
内容覆盖:
|
||
|
||
1. 架构概念
|
||
2. 前置准备(DSM 设置)
|
||
3. 如何通过 DSM 的 GUI 创建 MinIO / PostgreSQL / Zipline
|
||
4. 如何在 MinIO 创建 Bucket 和权限
|
||
5. Zipline 初始化与 API Token
|
||
6. n8n 如何接入
|
||
7. 文件持久化(防止 NAS 重启丢失)
|
||
8. 进阶部署选项(可选)
|
||
|
||
---
|
||
|
||
# 1. 架构图(Synology 专用)
|
||
|
||
```
|
||
[DSM Docker UI]
|
||
│
|
||
├── MinIO (9000 API, 9001 Console)
|
||
│ └── /volume1/docker/zipline-stack/minio/minio_data
|
||
│
|
||
├── PostgreSQL (Zipline DB)
|
||
│ └── /volume1/docker/zipline-stack/zipline/pg_data
|
||
│
|
||
└── Zipline (暴露 3333)
|
||
├── 前端上传 UI
|
||
└── n8n API 上传
|
||
```
|
||
|
||
Zipline → MinIO(S3) → NAS 存储
|
||
![[IMG-20251229190624349.png]]
|
||
|
||
---
|
||
|
||
# 2. 前置准备
|
||
|
||
## 2.1 确保 DSM 已安装
|
||
|
||
- **Container Manager**(DSM 7.2+ 自带,替代 Docker)
|
||
- **Docker**(DSM 7.1 及更早)
|
||
|
||
|
||
## 2.2 创建存储位置目录
|
||
|
||
DSM → File Station → 创建:
|
||
```
|
||
/volume1/docker/zipline-stack/minio/minio_data
|
||
/volume1/docker/zipline-stack/zipline/pg_data
|
||
```
|
||
|
||
---
|
||
## 2.3 **docker-compose.yml(可直接复制)**
|
||
|
||
``` bash
|
||
version: "3.9"
|
||
|
||
services:
|
||
minio:
|
||
image: minio/minio:latest
|
||
container_name: minio
|
||
command: server /data --console-address ":9001"
|
||
environment:
|
||
MINIO_ROOT_USER: admin
|
||
MINIO_ROOT_PASSWORD: Abcd_1234
|
||
ports:
|
||
- "9000:9000"
|
||
- "9001:9001"
|
||
volumes:
|
||
# 保留你精心组织的绝对路径
|
||
- /volume1/docker/zipline-stack/minio/minio_data:/data
|
||
restart: unless-stopped
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
# [已移除 CPU 限制以修复报错]
|
||
memory: 1G
|
||
reservations:
|
||
memory: 256M
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||
interval: 30s
|
||
timeout: 20s
|
||
retries: 3
|
||
|
||
postgres:
|
||
image: postgres:16
|
||
container_name: zipline_postgres
|
||
environment:
|
||
POSTGRES_USER: zipline
|
||
POSTGRES_PASSWORD: zipline
|
||
POSTGRES_DB: zipline
|
||
volumes:
|
||
# 保留你精心组织的绝对路径
|
||
- /volume1/docker/zipline-stack/zipline/pg_data:/var/lib/postgresql/data
|
||
restart: unless-stopped
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
# [已移除 CPU 限制以修复报错]
|
||
memory: 512M
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U zipline"]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 5
|
||
|
||
zipline:
|
||
image: ghcr.io/diced/zipline:latest
|
||
container_name: zipline
|
||
depends_on:
|
||
minio:
|
||
condition: service_healthy
|
||
postgres:
|
||
condition: service_healthy
|
||
environment:
|
||
DATABASE_URL: postgres://zipline:zipline@postgres:5432/zipline
|
||
CORE_SECRET: 22d5d3159d5ed51743bc8c8ef007f836
|
||
ZPLINE_ADMIN_USERNAME: admin
|
||
ZPLINE_ADMIN_PASSWORD: Abcd_1234
|
||
STORAGE_ENGINE: s3
|
||
S3_BUCKET: zipline-bucket
|
||
S3_ENDPOINT: http://minio:9000
|
||
S3_ACCESS_KEY: admin
|
||
S3_SECRET_KEY: Abcd_1234
|
||
S3_REGION: us-east-1
|
||
S3_FORCE_PATH_STYLE: "true"
|
||
PORT: 3000
|
||
ports:
|
||
- "3333:3000"
|
||
restart: unless-stopped
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
# [已移除 CPU 限制以修复报错]
|
||
memory: 512M
|
||
|
||
```
|
||
|
||
---
|
||
|
||
# 3. 你需要初始化 MinIO bucket(一次性)
|
||
|
||
进入 MinIO 控制台(浏览器):
|
||
```
|
||
http://192.168.3.17:9001/login
|
||
```
|
||
|
||
登录 → 创建 S3 Bucket:
|
||
```
|
||
zipline-bucket
|
||
```
|
||
|
||
设置为 public(否则图片无法直接访问):
|
||
- Buckets → zipline-bucket → _Access Rules_ →
|
||
Policy: **public read**
|
||
|
||
## 正确设置 Public Bucket(CE 下可行方案)
|
||
|
||
### 方法 :使用 `mc` 命令行(推荐)
|
||
|
||
1. 下载 MinIO CLI `mc` 到你的 DSM 或本地 PC:
|
||
```
|
||
wget https://dl.min.io/client/mc/release/linux-amd64/mc chmod +x mc
|
||
```
|
||
|
||
2. 添加 alias:
|
||
```
|
||
mc alias set local http://192.168.3.17:9000 admin StrongPasswordHere
|
||
```
|
||
|
||
3. 创建 public-read bucket:
|
||
```
|
||
mc mb local/zipline-bucket
|
||
```
|
||
|
||
4. 赋予匿名读写权限:
|
||
```
|
||
mc anonymous set public local/zipline-bucket
|
||
```
|
||
|
||
5. 测试:
|
||
```
|
||
mc ls local/zipline-bucket
|
||
```
|
||
|
||
现在这个 bucket 的对象就可以**被公开访问**了。
|
||
|
||
#### a、`mc`(MinIO Client)文档 &命令参考
|
||
|
||
- `mc anonymous` 命令:管理匿名(unauthenticated)访问策略。 [min.io+2min.io+2](https://min.io/docs/minio/linux/reference/minio-mc/mc-anonymous.html?utm_source=chatgpt.com)
|
||
- 支持子命令(`get` / `list` / `set` / `set-json` 等): [min.io](https://min.io/docs/minio/linux/reference/minio-mc/mc-anonymous.html?utm_source=chatgpt.com)
|
||
- `mc anonymous set` 语法(设置预定义策略):`none`, `download`, `upload`, `public` 四种选项可用。 [min.io+2min-io.cn+2](https://min.io/docs/minio/linux/reference/minio-mc/mc-anonymous-set.html?utm_source=chatgpt.com)
|
||
- `mc anonymous set-json`:可以提供一个自定义的 IAM JSON policy 来配置更细粒度权限。 [min.io](https://min.io/docs/minio/linux/reference/minio-mc/mc-anonymous-set-json.html?utm_source=chatgpt.com)
|
||
- `mc anonymous list`:查看某个 bucket 或前缀的匿名策略。 [min.io](https://min.io/docs/minio/linux/reference/minio-mc/mc-anonymous-list.html?utm_source=chatgpt.com)
|
||
|
||
#### b、可以设置的权限类型(匿名访问策略)
|
||
|
||
- `download`:只允许匿名用户下载对象(GET 操作)。 [min.io+1](https://min.io/docs/minio/linux/reference/minio-mc/mc-anonymous-set.html?utm_source=chatgpt.com)
|
||
- `upload`:只允许匿名用户上传对象(PUT 操作)。 [min.io+1](https://min.io/docs/minio/linux/reference/minio-mc/mc-anonymous-set.html?utm_source=chatgpt.com)
|
||
- `public`:既允许上传,也允许下载(等于读写权限)。 [min-io.cn+1](https://min-io.cn/docs/minio/linux/reference/minio-mc/mc-anonymous-set.html?utm_source=chatgpt.com)
|
||
- `none`:禁用匿名访问(恢复私有)。 [min.io](https://min.io/docs/minio/linux/reference/minio-mc/mc-anonymous-set.html?utm_source=chatgpt.com)
|
||
#### c、使用示例
|
||
假设你的 MinIO alias 是 `local`,bucket 名为 `mybucket`,你想:
|
||
|
||
- **设置 public(读写)权限**:
|
||
`mc anonymous set public local/mybucket`
|
||
- **设置只读(下载)权限**:
|
||
`mc anonymous set download local/mybucket`
|
||
- **设置只写(仅上传)权限**:
|
||
`mc anonymous set upload local/mybucket`
|
||
- **禁用匿名访问**:
|
||
`mc anonymous set none local/mybucket`
|
||
|
||
---
|
||
|
||
# 4. Zipline 初始化
|
||
|
||
访问:
|
||
``` bash
|
||
http://192.168.3.17:3333/dashboard
|
||
```
|
||
|
||
首次登陆使用:
|
||
- Username: `admin`
|
||
- Password: 你在 docker-compose的environment 中设置的
|
||
|
||
> [!NOTE] Docker Compose Environment Settings:
|
||
> S3_ACCESS_KEY: admin
|
||
> S3_SECRET_KEY: Abcd_1234
|
||
|
||
然后你可以:
|
||
- 生成 API Token(给 n8n)
|
||
- 设置上传规则
|
||
- 配置返回 URL(默认即可)
|
||
|
||
---
|
||
|
||
# 5. n8n 调用 Zipline 上传示例(最小可用)
|
||
|
||
https://zipline.diced.sh/docs/api
|
||
https://zipline.diced.sh/docs/api/upload
|
||
|
||
---
|
||
|
||
# 6. 性能分析(NAS 场景)
|
||
|
||
| 项目 | MinIO | Zipline |
|
||
| -------- | ---------------- | ----------------------- |
|
||
| 存储性能 | 只受 NAS 硬盘/SSD 限制 | 仅处理 metadata |
|
||
| 并发 | 高(S3 原生并行) | 中等(单 Node.js 进程) |
|
||
| 数据库 | 无(内置 KV) | PostgreSQL/SQLite,需要 DB |
|
||
| 扩展性 | 可横向扩容 | 单实例 → 前端微服务即可 |
|
||
| REST API | 完备 | 完备(适合 n8n) |
|
||
|
||
# 7. 备份策略
|
||
|
||
这是一个涉及**分布式存储系统一致性**的经典运维话题。由于 Zipline 将元数据存在 Postgres,将文件实体存在 MinIO,你的备份方案必须确保这两者在时间点上是(尽可能)一致的。
|
||
|
||
针对 Synology NAS 环境,我为你设计了两种方案。考虑到你的技术背景,我强烈推荐**热备份 + 增量归档**,这是企业级运维的标准做法。
|
||
## 核心挑战:由于“脑体分离”导致的一致性问题
|
||
- **大脑 (Postgres)**:记录了“文件A的ID是123,位于MinIO的/bucket/a.jpg”。
|
||
- **身体 (MinIO)**:实际存储了 `a.jpg`。
|
||
- **风险**:如果你在 10:00 备份了数据库,10:05 备份了 MinIO,但这 5 分钟内你上传了新文件,恢复时就会出现“数据库找不到文件”或“文件没记录”的幽灵数据。
|
||
|
||
---
|
||
## 方案:基于脚本的逻辑热备份
|
||
|
||
这种方案利用数据库自带的工具导出数据,结合文件系统的增量备份。
|
||
|
||
### 1. 工作原理
|
||
|
||
1. **数据库**:不停止服务,使用 `pg_dump` 命令将 Postgres 内存中的数据导出为一个 `.sql` 文件。这是“逻辑备份”。
|
||
2. **MinIO**:MinIO 的数据存储在物理磁盘上就是普通文件。
|
||
3. **归档**:使用 Synology Hyper Backup 将 `.sql` 文件和 `MinIO 数据目录` 一起备份到远端(云端、USB 硬盘或其他 NAS)。
|
||
### 2. 利弊分析
|
||
- **优点**:
|
||
- **零停机**:服务全程在线,不影响业务。
|
||
- **数据安全**:`pg_dump` 导出的 SQL 文件是纯文本,不依赖特定的 Postgres 版本或 CPU 架构(x86/ARM),**迁移能力极强**。
|
||
- **原生支持**:完美契合 Synology Hyper Backup 的增量备份机制。
|
||
- **缺点**:
|
||
- **微小的不一致性**:如果在导出 SQL 的几秒钟内恰好有文件上传,可能存在极小的时间差(对于个人/中小企业可忽略)。
|
||
- **配置门槛**:需要编写一个简单的 Shell 脚本。
|
||
|
||
### 3. 实施步骤
|
||
**第一步:创建备份存放目录** 在你的 NAS 上创建一个专门存放数据库备份文件的目录,例如: `/volume1/docker/zipline-stack/backups`
|
||
**第二步:编写自动备份脚本** 我为你写好了一个健壮的脚本,包含日志记录和旧备份自动清理功能。
|
||
请在 NAS 上创建一个文件,例如 `/volume1/docker/zipline-stack/backup_script.sh`,内容如下:
|
||
|
||
Bash
|
||
|
||
``` bash
|
||
#!/bin/bash
|
||
|
||
# ================= 配置区域 =================
|
||
# 备份保存路径
|
||
BACKUP_DIR="/volume1/docker/zipline-stack/backups"
|
||
# Postgres 容器名称 (需与 docker-compose.yml 一致)
|
||
PG_CONTAINER="zipline_postgres"
|
||
# 数据库用户和名称
|
||
PG_USER="zipline"
|
||
PG_DB="zipline"
|
||
# 保留多少天的备份
|
||
RETENTION_DAYS=30
|
||
# 当前日期
|
||
DATE=$(date +%Y%m%d_%H%M%S)
|
||
|
||
# ================= 执行逻辑 =================
|
||
mkdir -p "$BACKUP_DIR"
|
||
|
||
echo "[$DATE] 开始备份 Postgres..."
|
||
|
||
# 1. 执行 pg_dump 导出数据库 (压缩格式)
|
||
# 注意:这里不直接备份 /var/lib/postgresql/data 目录,因为热备份该目录会导致数据损坏
|
||
docker exec "$PG_CONTAINER" pg_dump -U "$PG_USER" -d "$PG_DB" | gzip > "$BACKUP_DIR/db_$DATE.sql.gz"
|
||
|
||
if [ $? -eq 0 ]; then
|
||
echo "[$DATE] 数据库备份成功: db_$DATE.sql.gz"
|
||
else
|
||
echo "[$DATE] !!! 数据库备份失败 !!!"
|
||
exit 1
|
||
fi
|
||
|
||
# 2. 清理旧备份 (删除超过 30 天的文件)
|
||
find "$BACKUP_DIR" -name "db_*.sql.gz" -mtime +$RETENTION_DAYS -delete
|
||
echo "[$DATE] 已清理超过 $RETENTION_DAYS 天的旧备份"
|
||
|
||
# 3. (可选) 如果你想在这里也把 MinIO 打包,可以用 tar,但建议交给 Hyper Backup 处理
|
||
# echo "MinIO 数据量较大,建议由 Synology Hyper Backup 直接备份 minio_data 目录"
|
||
|
||
echo "[$DATE] 备份流程结束。"
|
||
```
|
||
|
||
**第三步:设置脚本权限** SSH 进入 NAS,给脚本执行权限:
|
||
|
||
Bash
|
||
``` bash
|
||
chmod +x /volume1/docker/zipline-stack/backup_script.sh
|
||
```
|
||
|
||
**第四步:配置 Synology 任务计划 (Task Scheduler)**
|
||
|
||
1. 打开 DSM 控制面板 -> **任务计划**。
|
||
2. 新增 -> **计划的任务** -> **用户定义的脚本**。
|
||
3. **常规**:用户账号选择 `root` (必须,否则无法操作 Docker)。
|
||
4. **计划**:建议每天凌晨 3:00 执行。
|
||
5. **任务设置** -> 用户定义的脚本框中填入:
|
||
Bash
|
||
``` bash
|
||
bash /volume1/docker/zipline-stack/backup_script.sh >> /volume1/docker/zipline-stack/backup.log 2>&1
|
||
```
|
||
![[IMG-20251229190624937.png]]
|
||
![[IMG-20251229190625061.png]]
|
||
![[IMG-20251229190625079.png]]
|
||
|
||
**第五步:配置 Synology Hyper Backup** 这是最后一道防线。
|
||
|
||
1. 打开 **Hyper Backup**。
|
||
2. 创建一个新的数据备份任务。
|
||
|
||
3. **选择备份源**:
|
||
- 勾选 `/volume1/docker/zipline-stack/backups` (这里有刚才脚本生成的数据库 SQL)。
|
||
- 勾选 `/volume1/docker/zipline-stack/minio/minio_data` (这是图片实体文件)。
|
||
|
||
4. 设置备份目的地(USB、另一台 NAS 或 Synology C2 云)。
|
||
![[IMG-20251229190625099.png]]
|
||
![[IMG-20251229190625117.png]]
|
||
|
||
# Reference URL
|
||
|
||
|
||
- Docker Volume Documentation: [https://docs.docker.com/storage/volumes/](https://docs.docker.com/storage/volumes/)
|
||
- MinIO Docker Persistence: [https://min.io/docs/minio/linux/operations/install-deploy-manage/deploy-minio-single-node-single-drive.html](https://min.io/docs/minio/linux/operations/install-deploy-manage/deploy-minio-single-node-single-drive.html)
|
||
- Synology Docker Permissions Advice: [https://kb.synology.com/en-global/DSM/tutorial/How_to_manage_ACL_settings_on_your_Synology_NAS](https://kb.synology.com/en-global/DSM/tutorial/How_to_manage_ACL_settings_on_your_Synology_NAS)
|
||
- MinIO mc anonymous https://docs.min.io/enterprise/aistor-object-store/reference/cli/mc-anonymous/ |