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 才能上传文件:

  1. 左侧 Buckets → 右上角 Create Bucket
  2. 输入 Bucket 名称(如 dev-app-assets)
  3. 高级选项(版本控制、对象锁定)测试阶段保持关闭
  4. 点击 Create Bucket 保存

四、为开发人员创建专属账号

⚠️ 安全原则: 禁止把 Root 账号密码交给开发人员。每个使用方使用独立 Access Key,仅授予必要权限。

方式 A:Web 控制台创建(部分版本可用)

  1. IdentityUsersCreate User
  2. Access Key: 开发者账号名(如 dev-user-01)
  3. Secret Key: 设置强密码(至少8位,关闭页面后无法再次查看原文)
  4. Assign Policies: 勾选 readwrite(读写所有 Bucket)
  5. 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 公开访问(可选)

如果文件需被外部浏览器直接访问(如网站图片):

  1. Buckets → 点击目标 Bucket → Access Policy
  2. 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 里记录的历史凭证。

解决步骤

  1. 停止容器:docker compose down
  2. 删除数据目录下的 .minio.sys 文件夹(开启"显示隐藏文件"后找到并删除)
  3. 重新启动容器:docker compose up -d
  4. MinIO 发现目录为空,会重新读取环境变量初始化,再次执行 mc alias set 即可成功

⚠️ 此操作会清空账号权限配置,但已上传的实体文件不受影响。若存储桶已有重要数据,请先备份。


七、其他替代方案

方案 适用场景
SeaweedFS 海量小文件(数亿张图片),小文件性能优于 MinIO
Garage 多台地理位置分散的廉价服务器组成分布式集群
MinIO(本文) 通用场景,S3 兼容性好,单节点部署最简单