MinIO Practical Tutorial: Building lightweight S3-compatible storage from 0 to 1


🎯 Introduction

Traditional file storage (such as SMB/NAS) and heavy-duty Ceph/OSS solutions either lack cloud-native capabilities or have high deployment and maintenance costs. MinIO is a perfect compromise - lightweight, high-performance, fully compatible with Amazon S3 API, and can be deployed in private clouds. This article fully covers the three core areas of Installation and Configuration, Basic Management, and Python Rapid Integration, and is suitable for developers who are new to it or need to implement it quickly.


1️⃣ Quick installation: choose the method that suits you best

1.1 Docker single node (preferred for development/testing)

MinIO officially maintains the image, which can be done with one line of commands:

# 拉取最新稳定版(建议带版本号避免踩坑)
docker pull minio/minio:RELEASE.2026-04-06T05-26-02Z

# 启动单节点:挂载本地目录、映射API/控制台端口、配置默认密码
docker run -d \
  --name minio-local \
  --restart unless-stopped \
  -p 9000:9000 \
  -p 9001:9001 \
  -e "MINIO_ROOT_USER=minio_admin" \
  -e "MINIO_ROOT_PASSWORD=minio_strong_pwd123" \
  -v ./minio_data:/data \
  minio/minio:RELEASE.2026-04-06T05-26-02Z server /data --console-address ":9001"

Access after startuphttp://localhost:9001You can enter the Web console!


2️⃣ Basic concepts: clarify the S3 system in 3 minutes

ConceptPopular AnalogyMinIO Description
BucketFolders (the top level cannot be nested)Data container, globally uniquely named
ObjectFileCore unit of storage, with metadata
PolicyFolder/file permissionsAccess control rules in JSON format
mcCollection of Linux file commandsOfficial CLI management tool, more efficient than the Web

3️⃣ CLI tool mc: Quickly get started with common operations

3.1 Installation and configuration

# Linux/macOS安装
wget https://dl.min.io/client/mc/release/linux-amd64/mc  # macOS替换为darwin-amd64
chmod +x mc && sudo mv mc /usr/local/bin/

# 添加本地MinIO别名(后续用别名操作)
mc alias set local http://localhost:9000 minio_admin minio_strong_pwd123

# 测试连接
mc admin info local

3.2 Common bucket and file commands

# ---------------------- 存储桶操作 ----------------------
mc mb local/my_public_assets  # 创建存储桶
mc rb local/my_public_assets --force  # 强制删除非空存储桶
mc anonymous set public local/my_public_assets  # 设为公共读(适合静态资源)
mc anonymous set download local/my_public_assets  # 仅公共下载

# ---------------------- 文件操作 ----------------------
mc cp ./cat.jpg local/my_public_assets/  # 上传文件
mc cp --recursive ./photos/ local/my_public_assets/  # 递归上传目录
mc share download local/my_public_assets/cat.jpg --expire=30m  # 生成30分钟预签名URL

4️⃣ Python integration: 3 high-frequency scenarios in practice

4.1 Install dependencies

pip install minio flask pillow  # flask做API,pillow做图片处理

4.2 Scenario 1: Flask file upload service

from flask import Flask, request, jsonify
from minio import Minio
from minio.error import S3Error
import uuid
from werkzeug.utils import secure_filename

# 1. 初始化MinIO客户端
minio_client = Minio(
    "localhost:9000",
    access_key="minio_admin",
    secret_key="minio_strong_pwd123",
    secure=False  # 生产环境务必用HTTPS+true
)

# 2. 确保存储桶存在
if not minio_client.bucket_exists("user_uploads"):
    minio_client.make_bucket("user_uploads")

app = Flask(__name__)
ALLOWED_EXT = {"png", "jpg", "jpeg", "pdf", "mp4"}

def allowed_file(filename):
    return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXT

# 3. 上传接口
@app.route("/api/upload", methods=["POST"])
def upload():
    if "file" not in request.files:
        return jsonify({"msg": "无文件"}), 400
    file = request.files["file"]
    if file.filename == "" or not allowed_file(file.filename):
        return jsonify({"msg": "文件名空或格式不支持"}), 400

    try:
        # 生成唯一文件名避免冲突
        unique_name = f"{uuid.uuid4().hex}_{secure_filename(file.filename)}"
        # 直接上传内存中的文件(无需存本地临时文件)
        file_size = len(file.read())
        file.seek(0)
        minio_client.put_object(
            "user_uploads", unique_name, file, file_size,
            content_type=file.content_type
        )
        # 生成公共访问URL(前提是bucket设为public)
        public_url = f"http://localhost:9000/user_uploads/{unique_name}"
        return jsonify({"msg": "上传成功", "url": public_url})
    except S3Error as e:
        return jsonify({"msg": f"存储错误: {e}"}), 500

if __name__ == "__main__":
    app.run(debug=True, port=5000)

4.3 Scenario 2: Image thumbnail generation and storage

from PIL import Image
import io
from minio import Minio

minio_client = Minio("localhost:9000", "minio_admin", "minio_strong_pwd123", secure=False)
if not minio_client.bucket_exists("image_assets"):
    minio_client.make_bucket("image_assets")

def upload_with_thumb(original_img_path, thumb_size=(200, 200)):
    # 1. 读取原图
    with open(original_img_path, "rb") as f:
        original_data = f.read()
    original_name = original_img_path.split("/")[-1]
    thumb_name = f"thumb_{original_name}"

    # 2. 生成缩略图
    img = Image.open(io.BytesIO(original_data))
    img.thumbnail(thumb_size)
    thumb_buffer = io.BytesIO()
    img.save(thumb_buffer, format=img.format)
    thumb_buffer.seek(0)

    # 3. 批量上传
    minio_client.put_object("image_assets", original_name, io.BytesIO(original_data), len(original_data))
    minio_client.put_object("image_assets", thumb_name, thumb_buffer, thumb_buffer.getbuffer().nbytes)

    return f"http://localhost:9000/image_assets/{original_name}", f"http://localhost:9000/image_assets/{thumb_name}"

# 测试
original_url, thumb_url = upload_with_thumb("./cat.jpg")
print(f"原图: {original_url}")
print(f"缩略图: {thumb_url}")

5️⃣ Summary of best practices

Key PointsSpecific Recommendations
SecurityUse HTTPS in production environment, least privilege policy, rotate root key regularly
PerformanceSmall files can be merged in batches, and large files can be uploaded in parts (minio SDK automatically supports >100MB files)
Bucket namingLowercase letters, numbers, hyphens, globally unique
MetadataUsex-amz-meta-*Prefix stores business attributes (such as uploader ID, file status)

📝 Summary

MinIO is the preferred entry-level solution for private cloud object storage - simple deployment, S3 compatible, and mature ecosystem. The three high-frequency scenarios of Docker single-node development, mc quick management, and Python in this article have covered 90% of daily needs. If you need high-availability distributed deployment in the future, you can refer to the Erasure Code architecture description on the official website.