用 Docker 搭建 MinIO 对象存储:自托管 S3 兼容存储方案

为什么要自建对象存储?

做 AI 项目也好,搭个人网站也好,总得有个地方存文件。用阿里云 OSS 或者 AWS S3 可以,但数据不在自己手里,价格也不便宜。

MinIO 是目前最流行的开源对象存储方案,完全兼容 S3 API,Docker 一键部署,几百兆内存就能跑起来。

你能用它做什么?

  • 给 ChatGPT-Web、Rust-Desk 这些服务存用户上传的文件
  • 管理 AI 训练用的数据集和模型
  • 做网站静态资源托管
  • 备份数据库和配置文件
  • 搭建私有云盘

准备工作

你需要:

  • 一台 VPS(推荐 2 核 4G,磁盘至少 50G)
  • Docker 和 Docker Compose(已安装)
  • 基本 Linux 命令操作能力

磁盘规划建议

MinIO 对磁盘 IO 比较敏感,建议:

  • 系统盘装 Docker,数据盘单独挂载
  • 使用 SSD 或 NVMe,机械盘性能会差很多
  • 数据盘挂载到 /data 目录

第一步:创建项目目录

# 创建项目目录
mkdir -p ~/minio/{data,config}
cd ~/minio

# 设置权限
chmod 700 data

第二步:编写 Docker Compose

~/minio 目录下创建 docker-compose.yml

services:
  minio:
    image: minio/minio:latest
    container_name: minio
    restart: unless-stopped
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      MINIO_ROOT_USER: admin
      MINIO_ROOT_PASSWORD: 改成你的强密码
      MINIO_PROMETHEUS_AUTH_TYPE: public
    volumes:
      - ./data:/data
      - ./config:/root/.minio
    command: server /data --console-address ":9001"
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 30s
      timeout: 20s
      retries: 3

说明:

  • 端口 9000:S3 API 接口
  • 端口 9001:Web 管理控制台
  • MINIO_ROOT_USERMINIO_ROOT_PASSWORD:替换成你自己的账号密码

第三步:启动 MinIO

cd ~/minio
docker compose up -d

启动后等一会儿,检查容器状态:

docker ps | grep minio

看到 Up 状态就说明启动成功了。

查看日志确认:

docker logs minio

日志最后会显示:

MinIO Object Storage Server
API: http://0.0.0.0:9000
Console: http://0.0.0.0:9001

第四步:访问管理控制台

打开浏览器访问 http://你的IP:9001,用刚才设置的账号密码登录。

登录后你会看到:

  • Bucket 列表:空的,接下来要创建
  • 顶部菜单栏:浏览、登录用户、策略、设置

创建第一个 Bucket

点击左侧「创建 Bucket」:

  • Bucket 名称:填 my-files(全小写,只能含字母、数字、连字符和点)
  • 版本控制:暂时关闭
  • 点击「创建」

创建成功后,你可以在这里上传文件试试。

第五步:配置 S3 访问

使用 mc 命令行工具

MinIO 提供了 mc 命令行客户端,非常方便。

# 安装 mc
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/bin/

# 添加 MinIO 连接
mc alias set myminio http://localhost:9000 admin 你的密码

# 查看 bucket 列表
mc ls myminio

# 上传文件
mc cp ~/test.txt myminio/my-files/

# 下载文件
mc cp myminio/my-files/test.txt ~/downloaded.txt

代码中连接 S3

大多数编程语言都有 S3 SDK,直接改 endpoint 就能用 MinIO。

Python 示例:

import boto3

s3 = boto3.client(
    's3',
    endpoint_url='http://localhost:9000',
    aws_access_key_id='admin',
    aws_secret_access_key='你的密码',
    region_name='us-east-1'
)

# 上传文件
s3.upload_file('test.txt', 'my-files', 'test.txt')

# 列出所有文件
response = s3.list_objects_v2(Bucket='my-files')
for obj in response.get('Contents', []):
    print(obj['Key'])

第六步:配置 HTTPS(可选但推荐)

生产环境务必用 HTTPS,两种方式:

方案一:直接用 Caddy 反代(简单)

安装 Caddy:

# 一行安装 Caddy
curl -1sL 'https://caddyserver.com/api/v2/init' \
  | caddy load --output stdout > /usr/bin/caddy
chmod +x /usr/bin/caddy

# 安装 Caddy 插件(TLS)
caddy add-package github.com/caddy-dns/cloudflare  # 如果要用 DNS 验证

或者更简单的方式,用 Nginx 反代 + Certbot 自动签证书:

# 安装 Nginx
apt install nginx certbot python3-certbot-nginx -y

# 创建反代配置
sudo tee /etc/nginx/sites-available/minio <<'EOF'
server {
    listen 80;
    server_name minio.yourdomain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name minio.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/minio.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/minio.yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF

sudo ln -s /etc/nginx/sites-available/minio /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl restart nginx

# 申请证书
sudo certbot --nginx -d minio.yourdomain.com

证书申请后自动续期:

sudo systemctl enable certbot.timer

方案二:MinIO 自带 Let’s Encrypt

MinIO 支持直接配置 Let’s Encrypt:

environment:
  MINIO_SERVER_URL: https://minio.yourdomain.com
  MINIO_BROWSER_REDIRECT_URL: https://minio.yourdomain.com:9001

然后在 docker-compose 中加端口映射 443:443 即可。

第七步:防火墙设置

# UFW 防火墙示例
sudo ufw allow 9000/tcp  # S3 API
sudo ufw allow 9001/tcp  # 控制台
sudo ufw allow 443/tcp   # HTTPS
sudo ufw enable

验证是否成功

  1. 浏览器访问 http://你的IP:9001,能打开登录页面
  2. 登录后能看到刚创建的 Bucket
  3. 上传一个文件,能正常浏览和下载
  4. 运行 mc ls myminio,能看到刚才上传的文件
# 快速验证脚本
docker exec minio sh -c "mc mb myminio/test-bucket && mc mb myminio/test-bucket/sub && echo 'MinIO 运行正常 ✓'"

常见问题

Q: 容器启动后控制台打不开?

检查端口是否被占用:ss -tlnp | grep 9001。如果被占用了,改 docker-compose.yml 里的端口映射。

Q: 如何备份 MinIO 数据?

MinIO 的数据全在 ./data 目录,直接打包这个目录就行:

tar czf minio-backup-$(date +%F).tar.gz ~/minio/data

Q: 磁盘满了怎么办?

MinIO 默认使用 80% 容量时会进入「读保护模式」。你可以通过环境变量调整:

environment:
  MINIO_STORAGE_CLASS_STANDARD: EC:2

或者直接扩容磁盘。

Q: 如何创建只读权限的用户?

在控制台选择「登录用户」→「创建用户」→ 绑定一个策略,策略内容如下:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket", "s3:GetObject"],
      "Resource": ["arn:aws:s3:::my-files"]
    }
  ]
}

Q: 多服务器怎么部署?

MinIO 支持分布式部署,把多台服务器的磁盘组成一个池:

docker run -p 9000:9000 -p 9001:9001 \
  minio/minio server http://node{1...4}/data{1...2} \
  --console-address ":9001"

下一步

MinIO 只是一个起点。你可以:

  • 搭配 Cloudflare R2 做异地备份
  • 用 mc 脚本定期同步数据到其他服务器
  • 给 Bucket 设置生命周期规则,自动清理过期文件

数据在自己手里,才最安心。

这篇文章对你有帮助吗?