MinIO 是最流行的开源对象存储,完全兼容 Amazon S3 API。本文记录通过 Docker 部署最新版 MinIO 并完成 Bucket 创建、开发者账号分配与权限授权的完整过程。
一、Docker Compose 部署 MinIO
创建 docker-compose.yml:
version: '3.8'
services:
minio:
image: minio/minio:latest
container_name: minio-storage
ports:
- "9000:9000" # S3 API 通信端口(供代码/客户端调用)
- "9001:9001" # Web UI 管理控制台端口
environment:
MINIO_ROOT_USER: YOUR_ADMIN_USER # 建议修改为非默认账号
MINIO_ROOT_PASSWORD: YOUR_ADMIN_PASSWORD # 建议修改为强密码(至少8位)
volumes:
- ./data:/data # 宿主机存储目录
command: server /data --console-address ":9001"
restart: unless-stopped
核心提示: 两个端口缺一不可。
9000是供代码或 S3 客户端读写的 API 接口;9001是浏览器访问的图形化管理界面。
启动服务:
docker compose up -d
二、访问 Web 控制台
浏览器打开 http://<服务器IP>:9001,使用环境变量中配置的账号密码登录。
左侧导航栏说明:
| 菜单 | 用途 |
|---|---|
| Buckets | 创建和管理存储桶 |
| Identity → Users | 创建用户(需 Root 账号登录才显示,见排障章节) |
| Access Keys | 创建 API 密钥(部分新版单节点版本阉割了 UI 管理入口) |
三、创建存储桶(Bucket)
必须先创建 Bucket 才能上传文件:
- 左侧 Buckets → 右上角 Create Bucket
- 输入 Bucket 名称(如
dev-app-assets) - 高级选项(版本控制、对象锁定)测试阶段保持关闭
- 点击 Create Bucket 保存
四、为开发人员创建专属账号
⚠️ 安全原则: 禁止把 Root 账号密码交给开发人员。每个使用方使用独立 Access Key,仅授予必要权限。
方式 A:Web 控制台创建(部分版本可用)
- Identity → Users → Create User
- Access Key: 开发者账号名(如
dev-user-01) - Secret Key: 设置强密码(至少8位,关闭页面后无法再次查看原文)
- Assign Policies: 勾选
readwrite(读写所有 Bucket) - Save
方式 B:命令行创建(推荐,新版单节点 MinIO 通用)
如果 Web 控制台没有 Identity / Users 菜单,通过容器终端执行。
第一阶段:进入容器并初始化别名
# 进入 MinIO 容器内部
docker exec -it minio-storage sh
# 将本地 MinIO 绑定到别名(替换为你的真实 Root 账号密码)
mc alias set local http://127.0.0.1:9000 YOUR_ADMIN_USER YOUR_ADMIN_PASSWORD
第二阶段:创建存储桶与业务账号
# 创建存储桶(已在网页端创建过则忽略)
mc mb local/ehr
# 为业务系统创建专属调用账号
mc admin user add local ehr-app Ehr@2026Secure
第三阶段:配置业务隔离策略(核心)
为业务系统创建最小权限策略,限制其只能访问自己的桶,无法查看或操作其他桶:
cat <<EOF > ehr-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:*"],
"Resource": [
"arn:aws:s3:::ehr",
"arn:aws:s3:::ehr/*"
]
}
]
}
EOF
# 将策略文件导入 MinIO 并命名为 ehr-only
mc admin policy create local ehr-only ehr-policy.json
# 将策略绑定给 ehr-app 账号
mc admin policy attach local ehr-only --user ehr-app
💡 “业务隔离"安全原则: 每个业务系统使用独立账号+独立策略,该账号只能操作 ehr 这一个桶,无法跨界访问其他业务桶。符合最小权限原则(Principle of Least Privilege)。
第四阶段:交付给开发/实施人员
完成后只需提供以下四项信息:
| 配置项 | 示例值 |
|---|---|
| Endpoint | http://<服务器IP>:9000 |
| Access Key | ehr-app |
| Secret Key | Ehr@2026Secure |
| Bucket Name | ehr |
对方凭此凭证拥有对 ehr 桶的完整上传/下载/删除权限,但绝对无法访问该 MinIO 实例上的任何其他桶。
五、设置 Bucket 公开访问(可选)
如果文件需被外部浏览器直接访问(如网站图片):
- Buckets → 点击目标 Bucket → Access Policy
- 将
Private改为Public保存
⚠️ Public 仅允许任何人读取,上传/删除仍需有效凭证。
六、经典排障:.minio.sys 配置残留导致认证失败
mc alias set local http://127.0.0.1:9000 YOUR_ADMIN_USER YOUR_ADMIN_PASSWORD
# 返回: Unable to initialize new alias ... The Access Key Id you provided does not exist in our records
明明环境变量配置了账号,echo $MINIO_ROOT_USER 也显示正确,但 MinIO 拒绝认证。
根因
MinIO 的环境变量(MINIO_ROOT_USER / MINIO_ROOT_PASSWORD)只在数据目录完全为空时才会生效。
如果 ./data 目录过去被 MinIO 启动过,会在里面生成 .minio.sys 隐藏文件夹。此后 MinIO 会完全忽略当前环境变量,强制使用 .minio.sys 里记录的历史凭证。
解决步骤
- 停止容器:
docker compose down - 删除数据目录下的
.minio.sys文件夹(开启"显示隐藏文件"后找到并删除) - 重新启动容器:
docker compose up -d - MinIO 发现目录为空,会重新读取环境变量初始化,再次执行
mc alias set即可成功
⚠️ 此操作会清空账号权限配置,但已上传的实体文件不受影响。若存储桶已有重要数据,请先备份。
七、其他替代方案
| 方案 | 适用场景 |
|---|---|
| SeaweedFS | 海量小文件(数亿张图片),小文件性能优于 MinIO |
| Garage | 多台地理位置分散的廉价服务器组成分布式集群 |
| MinIO(本文) | 通用场景,S3 兼容性好,单节点部署最简单 |