#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"---
title: 1. 架构图（Synology 专用）
author: shenwei
tags: [docker, image, minio, n8n, nas, synology, zipline]
---
---
title: 1. 架构图（Synology 专用）
source:
author: shenwei
published:
created:
description:
tags: [docker, image, minio, n8n, nas, synology, zipline]
---

# 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/