香港服务器搭建Minio对象存储:替代AWS S3的私有化文件存储 + CDN分发完整方案
独立站用户上传的商品图片、用户头像、订单附件……这些文件放在哪里?放本地磁盘扩容麻烦,用 AWS S3 出口流量费昂贵,用阿里云 OSS 需要备案。在香港服务器上自托管 MinIO,获得完全兼容 S3 API 的对象存储,不仅成本比 S3 低 80%,数据也完全自主可控,结合 Cloudflare CDN 还能实现全球零出口流量费分发。
一、成本对比(1TB 数据,月均 1TB 流量)
| 方案 | 存储费 | 流量费 | 月总费 |
|---|---|---|---|
| AWS S3(标准) | $23($0.023/GB) | $90($0.09/GB) | $113 |
| Cloudflare R2 | $15($0.015/GB) | $0(免费出口) | $15 |
| 香港 VPS + MinIO(2TB盘) | ¥50~100(磁盘费用分摊) | 含在 VPS 套餐 | ¥50~100 |
二、Docker 部署 MinIO
<code"># /opt/minio/docker-compose.yml
version: '3.8'
services:
minio:
image: minio/minio:latest
container_name: minio
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: your_access_key # 相当于 S3 Access Key
MINIO_ROOT_PASSWORD: your_secret_key_32+ # 相当于 S3 Secret Key(8位以上)
MINIO_DOMAIN: storage.yourdomain.com # 用于路径/虚拟主机样式 URL
MINIO_BROWSER_REDIRECT_URL: https://minio-console.yourdomain.com
ports:
- "127.0.0.1:9000:9000" # API 端口
- "127.0.0.1:9001:9001" # Web 控制台
volumes:
- /data/minio:/data # 数据目录(建议挂载大容量磁盘)
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 10s
retries: 3<code"># 创建数据目录并启动 mkdir -p /data/minio cd /opt/minio && docker compose up -d # 访问 Web 控制台 # http://服务器IP:9001(通过 SSH 隧道访问,或配置 Nginx 反向代理)
三、Nginx 反向代理配置(API + 控制台)
<code"># MinIO API(S3 兼容接口)
server {
listen 443 ssl http2;
server_name storage.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/storage.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/storage.yourdomain.com/privkey.pem;
# 允许大文件上传
client_max_body_size 5G;
proxy_request_buffering off; # 关闭请求缓冲(大文件流式上传)
location / {
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $http_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;
proxy_connect_timeout 300;
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
}
}
# MinIO Web 控制台
server {
listen 443 ssl http2;
server_name minio-console.yourdomain.com;
# 限制只允许管理员 IP 访问控制台
allow 你的IP;
deny all;
location / {
proxy_pass http://127.0.0.1:9001;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
}
}四、Python 使用 MinIO(S3 兼容 SDK)
<code">import boto3
from botocore.config import Config
# 使用 boto3 连接 MinIO(S3 兼容,无需修改现有 S3 代码)
s3 = boto3.client(
's3',
endpoint_url='https://storage.yourdomain.com',
aws_access_key_id='your_access_key',
aws_secret_access_key='your_secret_key_32+',
config=Config(signature_version='s3v4'),
region_name='us-east-1' # MinIO 不校验 region,填任意值即可
)
# ── 创建 Bucket ──
s3.create_bucket(Bucket='product-images')
s3.create_bucket(Bucket='user-uploads')
# ── 上传文件 ──
def upload_product_image(product_id: str, file_path: str, content_type: str = 'image/webp'):
key = f"products/{product_id}/main.webp"
with open(file_path, 'rb') as f:
s3.put_object(
Bucket='product-images',
Key=key,
Body=f,
ContentType=content_type,
CacheControl='public, max-age=31536000', # 缓存1年
)
return f"https://storage.yourdomain.com/product-images/{key}"
# ── 生成预签名上传 URL(浏览器直接上传,不经过后端)──
def get_upload_url(file_name: str, content_type: str, expires: int = 3600):
"""
生成预签名 URL,前端直接 PUT 上传到 MinIO
避免文件经过后端服务器,减少后端带宽压力
"""
key = f"uploads/{file_name}"
url = s3.generate_presigned_url(
'put_object',
Params={
'Bucket': 'user-uploads',
'Key': key,
'ContentType': content_type,
},
ExpiresIn=expires
)
return {"upload_url": url, "file_key": key}
# ── 设置 Bucket 公开读取策略 ──
import json
public_policy = {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": ["*"]},
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::product-images/*"]
}]
}
s3.put_bucket_policy(
Bucket='product-images',
Policy=json.dumps(public_policy)
)五、Cloudflare CDN 加速 MinIO 文件
<code"># 在 Cloudflare 为 storage.yourdomain.com 添加 A 记录(开启橙色云朵代理) # 这样文件通过 Cloudflare 全球 CDN 节点分发,出口流量免费 # Cloudflare 缓存规则(针对 MinIO 静态文件) # 在 Cloudflare → Rules → Cache Rules 中添加: # 匹配条件:Hostname = storage.yourdomain.com AND URI Path 包含 /product-images/ # 缓存动作:Cache Everything,Edge TTL = 1 Month # 验证 CDN 缓存命中 curl -I https://storage.yourdomain.com/product-images/products/123/main.webp # 查看响应头:CF-Cache-Status: HIT(表示从 CDN 节点返回)
六、自动化备份 MinIO 数据
<code"># 使用 MinIO Client(mc)将数据同步到 Cloudflare R2 作为备份 docker run --rm -it minio/mc alias set myminio https://storage.yourdomain.com your_access_key your_secret_key docker run --rm -it minio/mc alias set r2 https://your-account.r2.cloudflarestorage.com R2_ACCESS_KEY R2_SECRET_KEY # 每日凌晨 3 点将 product-images 同步到 R2 备份 echo "0 3 * * * docker run --rm minio/mc mirror myminio/product-images r2/backup-product-images --overwrite" >> /etc/crontab
七、总结
MinIO + Cloudflare CDN 是香港服务器对象存储的最优组合:存储成本比 AWS S3 低 80%+,CDN 分发零出口流量费,S3 兼容 API 让现有代码无需修改。适合商品图片、用户上传、静态资源等场景,数据完全自主可控。