# Docker Minio
# 一、简介
高性能、分布式的对象存储系统,客户端支持java、python、Golang、Net、js等语言。应用场景广泛,可以存储海量图片,海量视频,海量文件(网盘)等。
- S3: Simple Storage Service
- Object
- Bucket
- Drive
- Set
纠删码:简称EC,是一种数据保护方法,将数据分割成片段,把冗余数据块扩展、编码,并将其存储在不同的位置,比如磁盘、存储节点或者其它地理位置。Minio采用Reed-Solomon code将对象拆分成N/2数据和N/2 奇偶校验块,通过纠删码校验算法可以恢复出正确的数据。
# 二、部署
# 单机部署
# 下载
wget https://dl.min.io/server/minio/release/linux-amd64/minio
# 修改用户名密码
export MINIO_ROOT_USER=username
export MINIO_ROOT_PASSWORD=password
# 启动
./minio server --console-address ":9090" /mnt/data
# 后台启动,指定日志路径
nohup ./minio server --console-address :"9090" ./miniodata/data >./miniodata/minio.log 2>&1 &
- 接口默认地址:9000
- 指定console端口:9090
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# Docker部署
docker run -p 19000:9000 -p 19001:9001 --name minio \
-d --restart=always \
-e MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE \
-e MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \
-v /root/minio/data:/data \
-v /root/minio/config:/root/.minio \
minio/minio server /data --console-address ":9001" --address ":9000"
#-e "MINIO_ROOT_USER=minio
#-e "MINIO_ROOT_PASSWORD=minio123456
#二选一
#-e MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
#-e MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
/root/minio/data
/root/minio/config
19000是服务间通讯端口,19001是访问控制界面的端口
http://localhost:19001 minio/minio123456
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
docker-compose 多机器集群部署
version: '3'
services:
# 访问 http://ip:9001/ 就可以进入web管理
# 可以提前在./minio/data1下新建一个bucket的名字。容器启动会直接放到容器的/data1下
minio:
container_name: minio
restart: always
privileged: true
image: minio/minio:latest
ports:
- "9000:9000"
- "9001:9001"
volumes:
- "./minio/data1:/data1"
- "./minio/data2:/data2"
- "./minio/data3:/data3"
- "./minio/data4:/data4"
#command: server --console-address ":9001" /data{1...4} # 9000是文件存储服务的port,9001是web界面的port
#command: server --console-address ":9001" http://minio{1...2}/data{1...4}
command: server --address ":9000" /data{1...4} --console-address ":9001" # 9000是文件存储服务的port,9001是web界面的port
environment:
- TZ=Asia/Shanghai
- MINIO_ROOT_USER=minio
- MINIO_ROOT_PASSWORD=minio...
- MINIO_PROMETHEUS_AUTH_TYPE=public
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
纠删码模式(略)
# 三、Java客户端使用
- 引入依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.6</version>
</dependency>
<!-- okhttp框架作为客户端 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 使用
public class MinioUtil {
private static final String URL = "http://192.168.198.129:19000";
private static final String ACCESS_KEY = "AKIAIOSFODNN7EXAMPLE";
private static final String SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY";
private static final int MIN_MULTIPART_SIZE = 5 * 1024 * 1024;
private static final String BUCKET = "test";
enum ContentType {
DEFAULT("default", "application/octet-stream"),
JPG("jpg", "image/jpeg"),
TIFF("tiff", "image/tiff"),
GIF("gif", "image/gif"),
JFIF("jfif", "image/jpeg"),
PNG("png", "image/png"),
TIF("tif", "image/tiff"),
ICO("ico", "image/x-icon"),
JPEG("jpeg", "image/jpeg"),
WBMP("wbmp", "image/vnd.wap.wbmp"),
FAX("fax", "image/fax"),
NET("net", "image/pnetvue"),
JPE("jpe", "image/jpeg"),
RP("rp", "image/vnd.rn-realpix");
@Getter
private String prefix;
@Getter
private String type;
ContentType(String prefix, String type) {
this.prefix = prefix;
this.type = type;
}
public static String getContentType(String prefix) {
if (StringUtils.isEmpty(prefix)) {
return DEFAULT.getType();
}
prefix = prefix.substring(prefix.lastIndexOf(".") + 1);
for (ContentType value : ContentType.values()) {
if (prefix.equalsIgnoreCase(value.getPrefix())) {
return value.getType();
}
}
return DEFAULT.getType();
}
}
private static MinioClient getMinioClient() {
return MinioClient.builder()
.endpoint(URL)
.credentials(ACCESS_KEY, SECRET_KEY)
.build();
}
/**
* 创建一个桶
*
* @param bucket 桶名称
*/
private void createBucket(String bucket) throws Exception {
MinioClient minioClient = getMinioClient();
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
if (!exists) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
}
}
/**
* 上传一个文件
*
* @param objectName 文件名称
* @param ins 文件流
* @param bucket 桶
*/
private void uploadFile(InputStream ins, String bucket, String objectName) throws Exception {
MinioClient minioClient = getMinioClient();
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucket)
.object(objectName)
.stream(ins, ins.available(), MIN_MULTIPART_SIZE)
.contentType(ContentType.getContentType(objectName))
.build());
}
/**
* 列出所有的桶
*/
public List<String> listBuckets() throws Exception {
List<Bucket> list = getMinioClient().listBuckets();
List<String> names = list.stream().map(Bucket::name).collect(Collectors.toList());
return names;
}
/**
* 列出桶里的对象
*/
public List<Map<String, Object>> listObjects(String bucket) throws Exception {
Iterable<Result<Item>> results = getMinioClient().listObjects(ListObjectsArgs.builder().bucket(bucket).recursive(true).build());
List<Map<String, Object>> files = new ArrayList<>();
results.forEach(i -> {
try {
Map<String, Object> file = new HashMap<>();
Item item = i.get();
file.put("name", item.objectName());
file.put("isDir", item.isDir());
files.add(file);
} catch (Exception e) {
e.printStackTrace();
}
});
return files;
}
/**
* 下载一个文件
*/
public InputStream download(String bucket, String objectName) throws Exception {
InputStream stream = getMinioClient().getObject(GetObjectArgs.builder().bucket(bucket).object(objectName).build());
return stream;
}
/**
* 删除一个桶
*/
public void deleteBucket(String bucket) throws Exception {
getMinioClient().removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
}
/**
* 删除一个对象
*/
public void deleteObject(String bucket, String objectName) throws Exception {
getMinioClient().removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());
}
public static void main(String[] args) throws Exception {
MinioUtil obj = new MinioUtil();
//1.创建桶
//obj.createBucket(BUCKET);
System.out.println(obj.listBuckets());
System.out.println(obj.listObjects(BUCKET));
//1.删除文件对象
//obj.deleteObject(BUCKET, "gonglu-cn.jpg");
//2.上传文件
File file = new File("E:\\baijq\\图片\\gonglu-cn.jpg");
try (FileInputStream fis = new FileInputStream(file)) {
obj.uploadFile(fis, BUCKET, "gonglu-cn.jpg");
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160