快速修复
# 1) 记录旧 MinIO 数据目录(本文示例 /tmp/trove-minio-test/data)
docker inspect minio --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{end}}'
# 2) 停旧容器(数据目录原样保留)
docker stop minio && docker rm minio
# 3) 整目录复制 + 属主对齐(RustFS 以 UID 10001 非 root 运行,必须 chown)
cp -a /tmp/trove-minio-test/data /tmp/trove-minio-test/data-rustfs
chown -R 10001:10001 /tmp/trove-minio-test/data-rustfs
# 4) 起 RustFS,端口约定与 MinIO 完全一致(9000 API / 9001 控制台)
docker run -d --name rustfs -v /tmp/trove-minio-test/data-rustfs:/data \
-e RUSTFS_ACCESS_KEY=rustfs-admin -e RUSTFS_SECRET_KEY='换成强密码' \
-p 9000:9000 -p 9001:9001 rustfs/rustfs:latest
# 5) 验证旧数据直接可见
docker logs rustfs | tail
你会遇到什么
MinIO 社区版 2025-12 官宣进入维护模式、2026-02 GitHub 仓库归档只读:不再有提交,已披露 CVE 不再修复,官方资源全部转向商业版 AIStor(订阅制)。还在用社区版跑文件服务(比如 Docker 部署的对象存储)等于抱着一个不再更新的黑盒。
另一个典型触发是:升级客户端后上传报 XAmzContentSHA256Mismatch——不是配置错了,是新版 AWS SDK 默认走流式分块签名,旧版 MinIO 解析不了,而且永远不会修。
本文路径:快速修复(30 秒一段命令)→ 一步步排查(可跳读)→ 原理与变体(症状/原因/证据)。赶时间直接跳到「快速修复」。
为什么会这样
- 停更是事实:MinIO 官方把社区版冻结,安全修复"视情况评估",仓库 README 标注 "THIS REPOSITORY IS NO LONGER MAINTAINED"。
- 签名不兼容是停更的伴生伤:新版 AWS SDK(v2)默认流式分块签名,旧 MinIO 只支持经典签名,报 XAmzContentSHA256Mismatch 且官方永不修复。
- 为什么能零丢失迁移:MinIO 磁盘上不是"一个对象一个文件",而是对象同名目录(xl.meta 元数据 + 分片)。RustFS 自 1.0.0-alpha.89 起直接兼容该磁盘格式——整目录
cp -a即可,数据不过网络,旧目录原样保留就是天然回退备份。
实测环境:Docker 29.1.3(WSL2 Ubuntu),minio/minio RELEASE.2025-09-07,rustfs/rustfs latest,2026-08-30。镜像经 docker.m.daocloud.io 加速拉取。
停更的真相在「生态契约」而不在代码本身:MinIO 社区版冻结后,上游(AWS SDK v2)继续演进,新版 SDK 默认流式分块签名而旧 MinIO 只支持经典签名——不是 MinIO「坏了」,是它不再跟随上游契约变化,签名握手必然失败且官方永不修复。
迁移零丢失的机制在磁盘格式:MinIO 不是「一个对象一个文件」,而是对象同名目录(xl.meta 元数据 + 分片);RustFS 直接兼容该磁盘格式意味着 cp -a 整目录搬迁 = 元数据与分片原样保留,数据不过网络。
确定性推论:判断 S3 兼容服务能否迁移,看「磁盘格式兼容」而非「API 兼容」(API 兼容可以随时断,磁盘格式兼容才能离线搬迁);旧目录原样保留就是天然回退备份——迁移后先验证读写,验证不过直接切回;判断路径:报 XAmzContentSHA256Mismatch = 签名代际不匹配,不是网络或配置问题。
一步步来
1. 停用旧 MinIO,但先记下数据目录 — 必做
docker inspect 的 Mounts 输出里记下 Source(宿主机路径)和 Destination(容器内路径,MinIO 一般是 /data)。旧容器删掉没关系,数据在宿主机目录里。
2. 整目录复制(不是挑文件) — 必做
ls /data/public 看到的不是图片文件,而是一堆和对象同名的目录(里面是 xl.meta 和分片),所以"挑对象复制"行不通。直接 cp -a 整个数据目录到平级新目录,旧目录原样保留 = 回退备份。
3. chown 10001 再启动(最容易崩的一步) — 必做
MinIO 官方镜像以 root 运行,挂哪都能写;RustFS 镜像 Dockerfile 声明 USER 10001,以非 root 身份运行,而 bind mount 不转换权限——容器内 UID 10001 写 /data 时按宿主机目录属主检查。不 chown 的话容器能起但写不进去。别用 chmod 777(等于向服务器所有用户开放写权限)。
4. 启动 RustFS 并验证 — 必做
docker ps状态 Up;docker logs rustfs无报错。- 控制台 http://服务器IP:9001 用启动时 AK/SK 登录,应直接看到旧 MinIO 的桶和文件。
- API 验证(S3 兼容):
list_buckets能看到旧桶、旧对象可读、新对象可写。
5. 客户端同步换(别忘) — 必做
旧 MinIO 的 Service Account 不会迁移:应用侧统一换 RustFS 启动时的新 AK/SK。Java/Go/Python SDK 只需改 endpoint + 凭据;IP 直连时 AWS SDK 需开 path-style 寻址(pathStyleAccessEnabled(true)),否则虚拟主机式寻址把桶名拼进域名会 DNS 解析失败。
怎么确认修好了
# S3 API 验证:旧桶可见 + 旧对象可读 + 新对象可写(实测输出)
buckets after migration: ['legacy-bucket']
legacy object readable: b'hello from minio legacy'
new object roundtrip: b'written on rustfs after migration'
浏览器控制台能看到旧桶旧文件 = 迁移端到端完成。
其它环境的表现
| 环境 | 说明 |
|---|---|
| 选型边界 | SeaweedFS 最成熟但 Master/Volume/Filer 多角色架构要重新学;Garage 适合地理分布式;Ceph 适合 PB 级。单机自用、中小规模、迁移成本最低选 RustFS |
| 生产规模 | 本次实测为单机 Docker 模拟存量 MinIO → RustFS 全链路;多节点纠删码、生产并发未测;PB 级核心存储选 SeaweedFS/Ceph 更稳 |
| 没换客户端 | 只换服务端不换 SDK,旧 MinIO Java SDK 仍能连 RustFS(S3 协议);建议顺手换 AWS SDK 标准实现,以后不绑任何一家 |
| 停更警示 | 对象存储选型不是一锤子买卖;S3 协议这层抽象才是值钱的——服务端换成谁都是配置级改动 |
| 客户端 SDK | Java/Go/Python 只需改 endpoint + AK/SK;IP 直连必须开 path-style(虚拟主机式寻址会 DNS 解析失败) |
症状
MinIO 社区版仓库归档只读 / README 标注不再维护;升级 AWS SDK 后上传报 XAmzContentSHA256Mismatch;Docker 部署的对象存储想迁移但怕丢数据。
原因
MinIO 官方资源转向商业版 AIStor,社区版 CVE 不再修复;新版 AWS SDK 默认流式分块签名而旧 MinIO 不支持(永不修复);RustFS 兼容 MinIO 磁盘格式(≥1.0.0-alpha.89),整目录复制即可零网络迁移。
解法
cp -a 整目录复制旧 MinIO 数据 → chown -R 10001:10001 → docker run 起 RustFS 挂载新目录 → 应用侧换新 AK/SK(IP 直连开 path-style)→ 控制台/API 验证旧桶旧对象 + 新写入。
验证证据
实测复现日志(2026-08-30)(2026-08-30 本地 Docker 全链路实测:建桶上传 → 停旧 → cp -a + chown → RustFS 起服 → 旧桶/旧对象直接可见 + 新对象 roundtrip 通过)
适用工具 (3)
本问题方案已挂到下列工具的方案页——从工具页也能回到这里,双向可达。
minio · 外部工具rustfs · 外部工具docker · 外部工具来源与证据
← 构建与部署 问题域 | 问题货架 | 遇到其它问题?去 问题空间 提交求助卡