基于 MinIO 对象存储和 Nginx 反向代理的高性能静态资源 CDN 解决方案。
- ✅ MinIO 对象存储:高性能的 S3 兼容对象存储
- ✅ Nginx 反向代理:智能缓存和负载均衡
- ✅ Docker 容器化:一键部署,开箱即用
- ✅ 多级缓存:浏览器缓存 + Nginx 缓存
- ✅ Gzip 压缩:自动压缩文本类资源
- ✅ 健康检查:自动监控服务状态
- ✅ 易于扩展:支持多 bucket 和自定义配置
客户端请求 → Nginx (80端口)
↓ (缓存命中直接返回)
↓ (缓存未命中)
MinIO (9000端口)
↓
存储文件系统
- Nginx 缓存:7天有效期,最大10GB
- 浏览器缓存:30天
- 缓存失效:404响应缓存1分钟
- Docker 20.10+
- Docker Compose 2.0+
# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f等待服务启动后(约10秒),运行初始化脚本:
# Windows PowerShell
.\scripts\init-minio.ps1或在 Linux/Mac 上:
chmod +x scripts/init-minio.sh
./scripts/init-minio.sh- CDN 访问地址: http://localhost/cdn/static/
- MinIO Console: http://localhost:9001
- 用户名:
admin - 密码:
admin123456
- 用户名:
- MinIO API: http://localhost:9000
- 健康检查: http://localhost/health
- 访问 http://localhost:9001
- 使用用户名
admin和密码admin123456登录 - 选择 bucket(如
static) - 点击 Upload 上传文件
# 配置别名
mc alias set mycdn http://localhost:9000 admin admin123456
# 上传文件
mc cp myfile.jpg mycdn/static/
# 上传整个目录
mc cp --recursive ./images/ mycdn/static/images/# 配置
aws configure set aws_access_key_id admin
aws configure set aws_secret_access_key admin123456
aws configure set default.region us-east-1
# 上传文件
aws --endpoint-url http://localhost:9000 s3 cp myfile.jpg s3://static/上传文件后,可以通过以下 URL 访问:
http://localhost/cdn/static/myfile.jpg
http://localhost/cdn/images/logo.png
http://localhost/cdn/videos/demo.mp4
访问资源时,响应头会包含缓存状态:
X-Cache-Status: HIT # 缓存命中
X-Cache-Status: MISS # 缓存未命中
X-Cache-Status: BYPASS # 跳过缓存
accetsCDN/
├── docker-compose.yml # Docker Compose 配置
├── .env # 环境变量
├── .gitignore # Git 忽略文件
├── README.md # 项目文档
├── config/ # 配置文件
│ ├── nginx/
│ │ ├── nginx.conf # Nginx 主配置
│ │ └── conf.d/
│ │ └── cdn.conf # CDN 站点配置
│ └── minio/ # MinIO 配置(自动生成)
├── data/ # 数据目录(自动生成)
│ ├── minio/ # MinIO 数据
│ └── nginx/
│ └── cache/ # Nginx 缓存
├── logs/ # 日志目录(自动生成)
│ └── nginx/
│ ├── access.log
│ └── error.log
└── scripts/ # 脚本文件
├── init-minio.sh # Linux/Mac 初始化脚本
└── init-minio.ps1 # Windows 初始化脚本
编辑 .env 文件修改 MinIO 配置:
MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=admin123456编辑 config/nginx/nginx.conf 调整缓存参数:
proxy_cache_path /var/cache/nginx/minio
levels=1:2
keys_zone=minio_cache:100m
max_size=10g # 最大缓存大小
inactive=60d # 缓存有效期
use_temp_path=off;编辑 config/nginx/conf.d/cdn.conf 修改路由规则:
location /cdn/ {
# 缓存有效期配置
proxy_cache_valid 200 304 7d; # 成功响应缓存 7 天
proxy_cache_valid 404 1m; # 404 响应缓存 1 分钟
# 浏览器缓存
expires 30d; # 浏览器缓存 30 天
}# 方式一:清除 Nginx 缓存目录
docker-compose exec nginx sh -c "rm -rf /var/cache/nginx/*"
docker-compose restart nginx
# 方式二:使用 purge 端点(需要本地访问)
curl -X PURGE http://localhost/purge-cache/static/myfile.jpg-
将 SSL 证书放到
ssl/目录:ssl/cert.pemssl/key.pem
-
修改
config/nginx/conf.d/cdn.conf:
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
# ... 其他配置
}- 重启服务:
docker-compose restart nginx编辑 config/nginx/nginx.conf:
worker_processes auto; # 自动设置为 CPU 核心数
worker_connections 4096; # 每个进程最大连接数proxy_cache_path ... max_size=50g; # 增加到 50GBlisten 443 ssl http2;# 查看容器状态
docker-compose ps
# 查看资源使用
docker stats
# 查看日志
docker-compose logs -f nginx
docker-compose logs -f minio# 查看缓存目录大小
docker-compose exec nginx du -sh /var/cache/nginx
# 查看缓存文件数量
docker-compose exec nginx find /var/cache/nginx -type f | wc -l# 备份 MinIO 数据
docker-compose exec minio mc mirror myminio/static /backup/static
# 或直接复制数据目录
Copy-Item -Recurse ./data/minio ./backup/minio-$(Get-Date -Format 'yyyyMMdd')A: 确保容器已启动,检查端口是否被占用:
docker-compose ps
netstat -ano | findstr :9001A: 检查响应头中的 X-Cache-Status,确保 MinIO 返回了正确的缓存头。
A: 修改 .env 文件中的 MINIO_ROOT_PASSWORD,然后重新创建容器:
docker-compose down
docker-compose up -dA: 清理旧的缓存文件或调整 max_size 参数:
docker-compose exec nginx sh -c "rm -rf /var/cache/nginx/*"# 停止服务
docker-compose stop
# 停止并删除容器
docker-compose down
# 删除容器和数据卷(谨慎使用)
docker-compose down -v
# 清理缓存和日志
Remove-Item -Recurse -Force ./data/nginx/cache/*
Remove-Item -Recurse -Force ./logs/*如果需要将配置好的 CDN 系统(包括已上传的静态资源)打包到其他服务器部署:
# 导出所有使用的镜像
docker save -o minio-image.tar minio/minio:latest
docker save -o nginx-image.tar nginx:alpine
# 或者打包为压缩文件
docker save minio/minio:latest | gzip > minio-image.tar.gz
docker save nginx:alpine | gzip > nginx-image.tar.gz# 创建备份目录
New-Item -ItemType Directory -Path "cdn-backup" -Force
# 备份 MinIO 数据(包含所有上传的文件)
Copy-Item -Recurse ./data/minio ./cdn-backup/data-minio
# 备份配置文件
Copy-Item -Recurse ./config ./cdn-backup/config
Copy-Item docker-compose.yml ./cdn-backup/
Copy-Item .env ./cdn-backup/
Copy-Item -Recurse ./scripts ./cdn-backup/
# 可选:备份 Nginx 缓存
Copy-Item -Recurse ./data/nginx/cache ./cdn-backup/data-nginx-cache
# 打包所有文件
Compress-Archive -Path ./cdn-backup/* -DestinationPath cdn-backup.zip创建 export-cdn.ps1:
# 完整 CDN 导出脚本
$exportDir = "cdn-export-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
$exportFile = "$exportDir.zip"
Write-Host "开始打包 CDN 系统..." -ForegroundColor Cyan
# 创建导出目录
New-Item -ItemType Directory -Path $exportDir -Force | Out-Null
# 1. 导出 Docker 镜像
Write-Host "导出 Docker 镜像..." -ForegroundColor Yellow
docker save minio/minio:latest | gzip > "$exportDir/minio-image.tar.gz"
docker save nginx:alpine | gzip > "$exportDir/nginx-image.tar.gz"
# 2. 备份配置和数据
Write-Host "备份配置文件..." -ForegroundColor Yellow
Copy-Item docker-compose.yml "$exportDir/"
Copy-Item .env "$exportDir/"
Copy-Item -Recurse config "$exportDir/"
Copy-Item -Recurse scripts "$exportDir/"
Copy-Item README.md "$exportDir/"
Copy-Item start.ps1 "$exportDir/"
Copy-Item stop.ps1 "$exportDir/"
# 3. 备份 MinIO 数据(静态资源)
Write-Host "备份 MinIO 数据..." -ForegroundColor Yellow
Copy-Item -Recurse data/minio "$exportDir/data-minio"
# 4. 创建导入脚本
Write-Host "创建导入脚本..." -ForegroundColor Yellow
@"
# CDN 导入和部署脚本
Write-Host "开始导入和部署 CDN 系统..." -ForegroundColor Cyan
# 1. 导入 Docker 镜像
Write-Host "导入 Docker 镜像..." -ForegroundColor Yellow
docker load -i minio-image.tar.gz
docker load -i nginx-image.tar.gz
# 2. 恢复目录结构
Write-Host "恢复目录结构..." -ForegroundColor Yellow
New-Item -ItemType Directory -Path "data/minio" -Force | Out-Null
New-Item -ItemType Directory -Path "data/nginx/cache" -Force | Out-Null
New-Item -ItemType Directory -Path "logs/nginx" -Force | Out-Null
# 3. 恢复 MinIO 数据
Write-Host "恢复 MinIO 数据..." -ForegroundColor Yellow
Copy-Item -Recurse data-minio/* data/minio/
# 4. 启动服务
Write-Host "启动服务..." -ForegroundColor Yellow
docker-compose up -d
Write-Host ""
Write-Host "部署完成!" -ForegroundColor Green
Write-Host "访问地址: http://localhost/cdn/static/" -ForegroundColor Cyan
Write-Host "MinIO Console: http://localhost:9001" -ForegroundColor Cyan
"@ | Out-File -FilePath "$exportDir/import-cdn.ps1" -Encoding UTF8
# 5. 打包所有文件
Write-Host "压缩打包..." -ForegroundColor Yellow
Compress-Archive -Path "$exportDir/*" -DestinationPath $exportFile -Force
# 清理临时目录
Remove-Item -Recurse -Force $exportDir
Write-Host ""
Write-Host "✅ 打包完成!" -ForegroundColor Green
Write-Host "导出文件: $exportFile" -ForegroundColor Cyan
Write-Host "文件大小: $([math]::Round((Get-Item $exportFile).Length/1MB, 2)) MB" -ForegroundColor White
Write-Host ""
Write-Host "部署步骤:" -ForegroundColor Yellow
Write-Host "1. 将 $exportFile 复制到目标服务器" -ForegroundColor White
Write-Host "2. 解压: Expand-Archive -Path $exportFile -DestinationPath cdn" -ForegroundColor White
Write-Host "3. 进入目录: cd cdn" -ForegroundColor White
Write-Host "4. 运行导入脚本: .\import-cdn.ps1" -ForegroundColor White# 解压导出的包
Expand-Archive -Path cdn-backup.zip -DestinationPath cdn-deploy
# 进入目录
cd cdn-deploy# 导入镜像
docker load -i minio-image.tar.gz
docker load -i nginx-image.tar.gz
# 验证镜像
docker images | Select-String "minio|nginx"# 创建必要的目录
New-Item -ItemType Directory -Path "data/nginx/cache" -Force
New-Item -ItemType Directory -Path "logs/nginx" -Force
# 确保 MinIO 数据已恢复(从备份复制)
# data/minio 应该已包含所有上传的文件# 启动所有服务
docker-compose up -d
# 查看状态
docker-compose ps
# 查看日志
docker-compose logs -f# 检查服务健康状态
curl http://localhost/health
# 访问已有的静态资源
# 如果之前上传了 test.jpg 到 static bucket
curl http://localhost/cdn/static/test.jpg
# 访问 MinIO Console
# 打开浏览器访问 http://localhost:9001另一种更简洁的方式是使用 Docker Volume:
# 1. 创建 volume 备份
docker run --rm -v accetscdn_minio_data:/data -v ${PWD}:/backup alpine tar czf /backup/minio-data-backup.tar.gz -C /data .
# 2. 在新服务器上恢复
docker volume create accetscdn_minio_data
docker run --rm -v accetscdn_minio_data:/data -v ${PWD}:/backup alpine tar xzf /backup/minio-data-backup.tar.gz -C /data创建 Makefile 或使用 CI/CD 工具:
# Makefile 示例
.PHONY: export import deploy
export:
@echo "导出 CDN 系统..."
@powershell -ExecutionPolicy Bypass -File export-cdn.ps1
import:
@echo "导入 CDN 系统..."
@powershell -ExecutionPolicy Bypass -File import-cdn.ps1
deploy: import
@echo "启动服务..."
@docker-compose up -d
@echo "部署完成!"- 数据完整性:确保在导出前停止服务或使用 MinIO 的快照功能
- 权限问题:恢复数据后检查文件权限,必要时调整
- 网络配置:检查目标服务器的端口是否开放(80, 443, 9000, 9001)
- 存储空间:确保目标服务器有足够的磁盘空间
- Docker 版本:确保目标服务器的 Docker 版本兼容
-
安全性
- 修改默认密码
- 配置防火墙规则
- 启用 HTTPS
- 限制 MinIO Console 访问
-
性能
- 使用 SSD 存储
- 调整缓存大小
- 启用 HTTP/2
- 配置 CDN 加速
-
可靠性
- 定期备份数据
- 配置监控告警
- 设置资源限制
- 使用健康检查
-
扩展性
- 使用 MinIO 集群模式
- 配置 Nginx 负载均衡
- 分离数据和应用
MIT License
如有问题,请提交 Issue 或参考官方文档: