第2-1-5章 docker安装MinIO实现文件存储服务-springboot整合minio-minio全网最全的资料
1. MinIO介绍
MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
官方文档:http://docs.minio.org.cn/docs 旧一点
2. MinIO应用场景
2.1 单主机单硬盘模式
2.2 单主机多硬盘模式
2.3 多主机多硬盘分布式
3. MinIO特点
-
高性能:作为高性能对象存储,在标准硬件条件下它能达到55GB/s的读、35GB/s的写速率
-
可扩容:不同MinIO集群可以组成联邦,并形成一个全局的命名空间,并跨越多个数据中心
-
云原生:容器化、基于K8S的编排、多租户支持
-
Amazon S3兼容:Minio使用Amazon S3 v2 / v4 API。可以使用Minio SDK,Minio Client,AWS SDK和AWS CLI访问Minio服务器。
-
可对接后端存储: 除了Minio自己的文件系统,还支持DAS、 JBODs、NAS、Google云存储和Azure Blob存储。
-
SDK支持: 基于Minio轻量的特点,它得到类似Java、Python或Go等语言的sdk支持
-
Lambda计算: Minio服务器通过其兼容AWS SNS / SQS的事件通知服务触发Lambda功能。支持的目标是消息队列,如Kafka,NATS,AMQP,MQTT,Webhooks以及Elasticsearch,Redis,Postgres和MySQL等数据库。
-
有操作页面
-
功能简单: 这一设计原则让MinIO不容易出错、更快启动
-
支持纠删码:MinIO使用纠删码、Checksum来防止硬件错误和静默数据污染。在最高冗余度配置下,即使丢失1/2的磁盘也能恢复数据
4. 存储机制
Minio使用纠删码erasure code和校验和checksum。 即便丢失一半数量(N/2)的硬盘,仍然可以恢复数据。
纠删码是一种恢复丢失和损坏数据的数学算法
5. docker安装MinIO
- 首先下载MinIO的Docker镜像:
-
先说下版本选择,这个可以自己去dockerhub上查看版本
-
由于minio更新迭代比较快,所以根据自己需要来选择版本,我用的是RELEASE.2022-09-22T18-57-27Z.fips这个版本
-
docker pull minio/minio:RELEASE.2022-09-22T18-57-27Z.fips
- 下载完成后使用如下命令运行MinIO服务,注意使用
--console-address
指定MinIO Console的运行端口(否则会随机端口运行):
docker run \
-p 9000:9000 \
-p 9001:9001 \
--name minio \
-d --restart=always \
-e "MINIO_ROOT_USER=admin" \
-e "MINIO_ROOT_PASSWORD=admin123456" \
-v /mydata/minio/data:/data \
-v /mydata/minio/config:/root/.minio \
minio/minio:RELEASE.2022-09-22T18-57-27Z.fips server /data --console-address ":9001"
6. docker-compose安装MinIO
version: '3'
services:
minio:
image: minio/minio:RELEASE.2022-09-22T18-57-27Z.fips
container_name: minio
environment:
MINIO_ROOT_USER: admin
MINIO_ROOT_PASSWORD: admin123456
command: server /data --console-address ":9001"
volumes:
- /mydata/minio/data:/data
- /mydata/minio/config:/root/.minio
ports:
- 9000:9000
- 9001:9001
- 运行成功后就可访问MinIO Console的管理界面了,输入账号密码
admin:admin123456
即可登录,访问地址:http://192.168.86.101:9000
7. MinIO Console使用
MinIO Console是MinIO自带的可视化管理工具,新版的功能还是很强大的。不仅支持了存储桶、文件的管理,还增加了用户、权限、日志等管理功能。
-
在存储文件之前,我们首先得创建一个存储桶
-
创建成功后,再上传一个文件
- 上传成功后如果你想从外部访问文件的话,需要把访问策略设置为公开,这里的策略除了公开和私有两种,也支持custom了。
- 之后把地址改为外网访问地址即可访问图片
8. 客户端使用
其实对于对象存储来说,MinIO Console的功能还是不够用的,所以官方还提供了基于命令行的客户端MinIO Client(简称mc),下面我们来讲讲它的使用方法。
8.1 常用命令
我们先来熟悉下mc的命令,这些命令和Linux中的命令有很多相似之处。
命令 | 作用 |
---|---|
ls | 列出文件和文件夹 |
mb | 创建一个存储桶或一个文件夹 |
rb | 删除一个存储桶或一个文件夹 |
cat | 显示文件和对象内容 |
pipe | 将一个STDIN重定向到一个对象或者文件或者STDOUT |
share | 生成用于共享的URL |
cp | 拷贝文件和对象 |
mirror | 给存储桶和文件夹做镜像 |
find | 基于参数查找文件 |
diff | 对两个文件夹或者存储桶比较差异 |
rm | 删除文件和对象 |
events | 管理对象通知 |
watch | 监听文件和对象的事件 |
policy | 管理访问策略 |
session | 为cp命令管理保存的会话 |
config | 管理mc配置文件 |
update | 检查软件更新 |
version | 输出版本信息 |
8.2 安装及配置
由于MinIO服务端中并没有自带客户端,所以我们需要安装并配置完客户端后才能使用,这里以Docker环境下的安装为例。
- 下载MinIO Client 的Docker镜像
docker pull minio/mc:latest
- 在Docker容器中运行mc
docker run -it --entrypoint=/bin/sh minio/mc
- 运行完成后我们需要进行配置,将我们自己的MinIO服务配置到客户端上去,配置的格式如下
mc config host add <ALIAS> <YOUR-S3-ENDPOINT> <YOUR-ACCESS-KEY> <YOUR-SECRET-KEY>
- 对于我们的MinIO服务可以这样配置
mc config host add minio http://192.168.86.101:9000 admin admin123456
8.3 常用操作
下面这些就用macro大神的教程,我就不继续实操了,我本地没有装客户端,因为通过console控制台管理足够日常使用了
- 查看存储桶和查看存储桶中存在的文件
# 查看存储桶
mc ls minio
# 查看存储桶中存在的文件
mc ls minio/blog
- 创建一个名为
test
的存储桶
mc mb minio/test
- 共享
avatar.png
文件的下载路径
mc share download minio/blog/avatar.png
- 查找
blog
存储桶中的png文件
mc find minio/blog --name "*.png"
- 设置
test
存储桶的访问权限为只读
。
# 目前可以设置这四种权限:none, download, upload, public
mc policy set download minio/test/
# 查看存储桶当前权限
mc policy list minio/test/
9. 兼容AWS S3
当我们对接第三方服务要用到对象存储时,这些服务往往都是支持AWS S3的。比如说一个直播的回放功能,需要对象存储来存储回放的视频,由于MinIO兼容AWS S3的大多数API,我们可以直接拿它当AWS S3来使用。
- 我们可以下载个AWS S3的客户端来试试,MinIO到底能不能支持S3的API,这里使用的是
S3 Browser
,下载地址:https://s3browser.com/
- 安装好
S3 Browser
之后,添加一个Account,输入相关登录信息,注意选择Account类型为S3 Compatible Storage
- 连接成功后,我们可以看见之前我们创建的存储桶和上传的文件
S3 Browser
这个工具功能还是很强大的
- 如果你想修改存储桶的访问权限的话直接通过
Permissions
标签修改即可。
10. 利用Java客户端调用MinIO
参考文档:https://docs.min.io/docs/java-client-api-reference.html
10.1 引入依赖
在service-product模块中添加依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.0</version>
</dependency>
10.2 添加配置文件
minio:
endpointUrl: http://IP:9000
accessKey: admin
secreKey: admin123456
bucketName: file
10.3 编写java程序
@RestController
@RequestMapping("admin/product")
public class FileUploadController {
// 获取文件上传对应的地址
@Value("${minio.endpointUrl}")
public String endpointUrl;
@Value("${minio.accessKey}")
public String accessKey;
@Value("${minio.secreKey}")
public String secreKey;
@Value("${minio.bucketName}")
public String bucketName;
// 文件上传控制器
@PostMapping("fileUpload")
public Result fileUpload(MultipartFile file) throws Exception{
// 准备获取到上传的文件路径!
String url = "";
// 使用MinIO服务的URL,端口,Access key和Secret key创建一个MinioClient对象
// MinioClient minioClient = new MinioClient("https://play.min.io", "Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG");
MinioClient minioClient =
MinioClient.builder()
.endpoint(endpointUrl)
.credentials(accessKey, secreKey)
.build();
// 检查存储桶是否已经存在
boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if(isExist) {
System.out.println("Bucket already exists.");
} else {
// 创建一个名为asiatrip的存储桶,用于存储照片的zip文件。
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
}
// 定义一个文件的名称 : 文件上传的时候,名称不能重复!
String fileName = System.currentTimeMillis()+ UUID.randomUUID().toString();
// 使用putObject上传一个文件到存储桶中。
// minioClient.putObject("asiatrip","asiaphotos.zip", "/home/user/Photos/asiaphotos.zip");
minioClient.putObject(
PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build());
// System.out.println("/home/user/Photos/asiaphotos.zip is successfully uploaded as asiaphotos.zip to `asiatrip` bucket.");
// 文件上传之后的路径: http://192.168.86.101:9000/file/xxxxxx
url = endpointUrl+"/"+bucketName+"/"+fileName;
System.out.println("url:\t"+url);
// 将文件上传之后的路径返回给页面!
return Result.ok(url);
}
}