docker-compose搭建minio對象存儲服務器

docker-compose搭建minio對象存儲服務器

最近想使用oss對象存儲進行用戶圖片上傳的管理,了解了一下例如aliyun或者騰訊云的oss對象存儲服務,但是呢涉及到對象存儲以及經費有限的緣故,決定自己手動搭建一個oss對象存儲服務器;

首先大致了解一下對象存儲:

對象存儲OSS(Object Storage Service)是一種云存儲服務,它提供了海量、安全、低成本、高可靠的存儲解決方案

然后在經過大致了解后,選擇了MiNiO,進行oss對象服務器的搭建工作,MinIO是一個開源的對象存儲服務器,它兼容Amazon S3 API,并提供高性能、高可用性的存儲解決方案。在本文中,我們將介紹如何使用Docker Compose快速部署MinIO。

一、docker-compose中的minio對象服務部署

準備工作:

1、服務器必須安裝docker

2、服務器必須安裝docker對應版本的docker-compose

1.1獲取鏡像:

首先,如果你的docker還能連上網,能夠通過docker pull相關的鏡像(咳咳,最近docker不對勁,拉取不到鏡像),如果可以拉取鏡像,可以執行下述命令:

docker pull minio/minio:latest

如果不可以,建議在往上下載一個minio的tar包,上傳至服務器后,可以執行以下命令:

docker load -i minio.tar  ## minio 是你自己tar包的名字。

通過上述操作后,可以使用 docker images 進行查看獲取到的鏡像
請添加圖片描述

1.2 docker-compose.yml文件制作

vim docker-compose.yml

先貼一個代碼叭,一會兒挨個兒解釋:

version: '3'
services:minio:image: minio/miniocontainer_name: minioports:- 9010:9000- 9011:9011environment:TZ: Asia/ShanghaiMINIO_ACCESS_KEY: minioMINIO_SECRET_KEY: minio123volumes:- ./data:/datacommand: server /data --console-address ":9011"

大概配置如上所示,有幾點注意

注:

1、minio容器默認使用兩個端口,9000和9001 9000端口主要適用于數據傳輸,9001端口主要是用于管理界面,上述文件中我為了好記且避免端口沖突,將9000端口映射到了服務器的9010端口,將9001端口改成了9011并映射到了服務器的9011端口

2、數據卷映射: 默認將數據卷映射到了docker-compose.yml同文件目錄下的data文件夾

3、command: server --console-address ‘:9011’ /data 這行一定要加,否則端口號是隨機的,你壓根映射不出去

4、新版本中用戶名和密碼改用成了 “MINIO_ROOT_USER” 和 “MINIO_ROOT_PASSWORD” 舊版本是 “MINIO_ACCESS_KEY” 和 “MINIO_SECRET_KEY” 可以自己按照版本進行設置。

5、4中分別對應的是管理界面的用戶名和密碼

在編輯docker-compose.yml并保存后,通過下述命令創建并啟動minio容器

#如果你的docker-compose.yml文件中有好幾個容器,你并不想啟動其他容器,只想啟動minio
docker-compose up -d minio
#如果你的docker-compose.yml文件中只有目前的minio
docker-compose up -d 

啟動成功后會看到服務器顯示

請添加圖片描述

此時可以在瀏覽器輸入 上面docker-compose.yml文件中的【你自己的IP+9011】 訪問minio的控制面板,記得開啟防火墻9010,9011端口喲~

請添加圖片描述

輸入用戶名和密碼,登錄minio控制面板

請添加圖片描述

至此呢 單機版本 通過docker-compose 部署minio對象存儲結束

二、spring-boot 集成 minio 對象存儲

1、自己創建spring-boot 工程,在這里不多贅述

2、引入pom依賴

在自己的boot項目中引入minio依賴

<!---minio cos對象存儲--><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.4.0</version></dependency>

3、集成代碼

在集成代碼之前呢,首先了解一下minio的幾個知識點

  • Object:存儲到Minio的基本對象,如文件、字節流、Anything…
  • Bucket:用來存儲Object的邏輯空間。每個Bucket之間的數據量是互相隔離的。對于客戶端而言,就相當于一個存放文件的頂層文件夾。
  • Drive:即存儲數據的磁盤,在Minio啟動時,以參數的方式傳入。Minio中所有的對象數據都會存儲在Drive里。
  • Set:即一組Drive的集合,分布式部署根據集群規模自動劃分一個或多個Set,每個Set中的Drive分布在不同位置。一個對象存儲在一個Set上.(for example:{1…64} is divided into 4 sets each of size 16)
    • 一個對象存儲在一個Set上
    • 一個集群劃分為多個Set
    • 一個Set包含的Drive數量是固定的,默認由系統根據集群規模自動計算得出
    • 一個Set中我的Drive盡可能分布在不同的節點上
3.1 創建用戶,創建桶

可以在minio控制面板進行用戶的創建以及存儲桶(bucket)的創建。我們創建一個test的桶以及創建一個用戶并賦予讀寫的權限

請添加圖片描述

請添加圖片描述

3.2 添加application.yml配置文件
minio:url: http://xxxxxxx #Minio服務所在地址bucketName: xxxxxx #存儲桶名稱accessKey: testUser #創建用戶訪問的key secretKey: 000000000 #創建用戶 訪問的秘鑰
3.3 引入配置

創建MinioConfig 配置文件,將MinioClient 注入容器

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {/*** 服務地址*/private String url;/*** 用戶名*/private String accessKey;/*** 密碼*/private String secretKey;/*** 存儲桶名稱*/private String bucketName;/*** 預覽到期時間(小時)*/private Integer previewExpiry;@Beanpublic MinioClient getMinIOClient() {return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();}
}
3.4 引入相關操作

創建MinioCosManger文件 封裝了minio客戶端的一些操作

@Component
@Slf4j
public class MinioCosManger {@Autowiredprivate MinioConfig prop;@Resourceprivate MinioClient minioClient;/*** 查看存儲bucket是否存在** @return boolean*/public Boolean bucketExists(String bucketName) {Boolean found;try {found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return found;}/*** 創建存儲bucket** @return Boolean*/public Boolean makeBucket(String bucketName) {try {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 刪除存儲bucket** @return Boolean*/public Boolean removeBucket(String bucketName) {try {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 獲取全部bucket*/public List<Bucket> getAllBuckets() {try {List<Bucket> buckets = minioClient.listBuckets();return buckets;} catch (Exception e) {e.printStackTrace();}return null;}/*** 文件上傳** @param file 文件* @return Boolean*/public String upload(MultipartFile file) {String originalFilename = file.getOriginalFilename();if (StringUtils.isBlank(originalFilename)) {throw new RuntimeException();}String fileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));String dateFormat = "yyyy-MM/dd";DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat);LocalDate nowDate = LocalDate.now();String format = nowDate.format(formatter);String objectName = format + "/" + fileName;try {PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(prop.getBucketName()).object(objectName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();//文件名稱相同會覆蓋minioClient.putObject(objectArgs);} catch (Exception e) {e.printStackTrace();return null;}return objectName;}/*** 預覽圖片** @param fileName* @return*/public String preview(String fileName) {// 查看文件地址GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(prop.getBucketName()).object(fileName).method(Method.GET).build();try {String url = minioClient.getPresignedObjectUrl(build);return url;} catch (Exception e) {e.printStackTrace();}return null;}/*** 文件下載** @param fileName 文件名稱* @param res      response* @return Boolean*/public void download(String fileName, HttpServletResponse res) {GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build();try (GetObjectResponse response = minioClient.getObject(objectArgs)) {byte[] buf = new byte[1024];int len;try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {while ((len = response.read(buf)) != -1) {os.write(buf, 0, len);}os.flush();byte[] bytes = os.toByteArray();res.setCharacterEncoding("utf-8");// 設置強制下載不打開// res.setContentType("application/force-download");res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);try (ServletOutputStream stream = res.getOutputStream()) {stream.write(bytes);stream.flush();}}} catch (Exception e) {e.printStackTrace();}}/*** 查看文件對象** @return 存儲bucket內文件對象信息*/public List<Item> listObjects() {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(prop.getBucketName()).build());List<Item> items = new ArrayList<>();try {for (Result<Item> result : results) {items.add(result.get());}} catch (Exception e) {e.printStackTrace();return null;}return items;}/*** 刪除** @param fileName* @return* @throws Exception*/public boolean remove(String fileName) {try {minioClient.removeObject(RemoveObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build());} catch (Exception e) {return false;}return true;}}
3.5 創建controller進行測試
/*** @version 1.0* @Author jerryLau* @Date 2024/7/1 11:23* @注釋*/
@Api(tags = "文件相關接口")
@Slf4j
@RestController
@RequestMapping(value = "product/file")
public class FileController2 {@Autowiredprivate MinioCosManger minioUtil;@Autowiredprivate MinioConfig prop;@ApiOperation(value = "查看存儲bucket是否存在")@GetMapping("/bucketExists")public BaseResponse<String> bucketExists(@RequestParam("bucketName") String bucketName) {if (minioUtil.bucketExists(bucketName)) {return ResultUtils.success("bucketName is exit!");} elsereturn ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "bucketName is not exit!");}@ApiOperation(value = "創建存儲bucket")@GetMapping("/makeBucket")public BaseResponse<String> makeBucket(String bucketName) {if (minioUtil.makeBucket(bucketName)) {return ResultUtils.success("create bucket success!");} elsereturn ResultUtils.error(ErrorCode.OPERATION_ERROR, "create bucket error!");}@ApiOperation(value = "刪除存儲bucket")@GetMapping("/removeBucket")public BaseResponse<String> removeBucket(String bucketName) {if (minioUtil.removeBucket(bucketName)) {return ResultUtils.success("removeBucket  success!");} elsereturn ResultUtils.error(ErrorCode.OPERATION_ERROR, "removeBucket error!");}@ApiOperation(value = "獲取全部bucket")@GetMapping("/getAllBuckets")public BaseResponse<List<Bucket>> getAllBuckets() {List<Bucket> allBuckets = minioUtil.getAllBuckets();return ResultUtils.success(allBuckets);}@ApiOperation(value = "文件上傳返回url")@PostMapping("/upload")public BaseResponse<String> upload(@RequestParam("file") MultipartFile file) {String objectName = minioUtil.upload(file);if (null != objectName) {String url = (prop.getUrl() + "/" + prop.getBucketName() + "/" + objectName);return ResultUtils.success(url);}return ResultUtils.error(ErrorCode.OPERATION_ERROR, "upload error!");}@ApiOperation(value = "圖片/視頻預覽")@GetMapping("/preview")public BaseResponse<String> preview(@RequestParam("fileName") String fileName) {String preview = minioUtil.preview(fileName);return ResultUtils.success(preview);}@ApiOperation(value = "文件下載")@GetMapping("/download")public void download(@RequestParam("fileName") String fileName, HttpServletResponse res) {minioUtil.download(fileName, res);}@ApiOperation(value = "刪除文件", notes = "根據url地址刪除文件")@PostMapping("/delete")public BaseResponse<String> remove(String url) {String objName = url.substring(url.lastIndexOf(prop.getBucketName() + "/") + prop.getBucketName().length() + 1);boolean remove = minioUtil.remove(objName);if (remove) {return ResultUtils.success(objName + "delete success!");} else return ResultUtils.error(ErrorCode.OPERATION_ERROR, objName + "delete error!");}}
3.6 接口測試以及存儲驗證

通過knife4j或者其他請求測試工具(postman、apifox等),測試接口

請添加圖片描述

注意:

1、按照理論來說在上傳結束后返回的這個文件的url應該沒有辦法直接訪問,應該在訪問該存儲對象的時候,去調用preview方法,但是對本人而言,調用preview返回的地址太長了,并且存在一定的時效性,在超過一段時間后將不會在被訪問到,所以本人通過給bucket設置access prefix為 readandwrite,這樣一來,上傳接口的返回url便可直接被訪問到了。

2、如果想去調用preview 或者download 方法時,所傳入的文件名一定是bucket后面的全部文件名稱,比如上面測試圖片中,如果調用,傳入文件名應為2024-07/01/0011c366-f2a4-4b26-adbc-931d444d7205.png 而不是簡單的0011c366-f2a4-4b26-adbc-931d444d7205.png ,否則即使返回了preview的url ,這個url也無法被訪問到。

請添加圖片描述


至此,通過docker-compose手動搭建minio 對象存儲服務器已全部完結,喜歡的觀眾老爺,請一鍵三連 🎉🎉🎉,感謝大家~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/37849.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/37849.shtml
英文地址,請注明出處:http://en.pswp.cn/web/37849.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

燒結銀到底有多牛?歡迎咨詢SHAREX善仁新材研究院

燒結銀到底有多牛&#xff1f;歡迎咨詢SHAREX善仁新材研究院 在當今日新月異的科技浪潮中&#xff0c;材料科學以其獨特的魅力引領著人類探索未知領域的步伐。在眾多前沿材料中&#xff0c;燒結銀憑借其卓越的性能和廣泛的應用前景&#xff0c;逐漸嶄露頭角&#xff0c;成為科…

創建XCOM窗體和跳轉連接

Xcom 窗體&#xff1a; (groupBox組合框&#xff0c;comboBox下拉框) xcom代碼&#xff1a; namespace _01_作業 {// 1kb 1024B 1200B// 1MB public partial class Form1 : Form{public List<string> botelv new List<string> { "600","1200&…

Unix Network Programming Episode 96

‘socketpair’ Function The socketpair function creates two sockets that are then connected together. This function applies only to Unix domain sockets. #include <sys/socket.h> int socketpair(int family, int type, int protocol, int sockfd[2]);POSIX…

(十七)如何學習統計學基礎知識(學習路線)

統計學是數據科學的基本支柱。統計學的目的是幫助你理解數據并從中得出有意義的結論。在數據科學中&#xff0c;統計學在理解數據模式和趨勢、做出預測和檢驗假設方面起著至關重要的作用。 (一) 數據科學統計學習路線圖 本文為學習統計學并將其應用于數據科學提供了清晰、結構化…

如何使用 SPM 插件從 Pkl 配置文件生成 Swift 接口

文章目錄 前言示例展示 Pkl 配置生成 Swift 綁定手動安裝和使用 pkl-gen-swift創建 SPM 命令插件加載 Pkl 配置總結前言 Pkl(全稱為 Pickle)是蘋果推出的一種全新的專用于配置的編程語言。它允許開發人員通過類型和內置驗證安全、直觀地設計數據模型。 作為蘋果語言,Pkl 有…

Python容器 之 列表--下標和切片

列表的切片 得到是 新的列表字符串的切片 得到是 新的字符串 如果下標 不存在會報錯 list1 [1, 3.14, "hello", False] print(list1)# 獲取 列表中 第一個數據 print(list1[0]) # 1# 獲取列表中的最后一個數據 print(list1[-1]) # [False]# 獲取中間兩個數 即 3.1…

3.2ui功能講解之graph頁面

本節重點介紹 : graph頁面target頁面flags頁面status頁面tsdb-status頁面 訪問地址 $ip:9090 graph頁面 autocomplete 可以補全metrics tag信息或者 內置的關鍵字 &#xff0c;如sum聚合函數table查詢 instante查詢&#xff0c; 一個點的查詢graph查詢調整分辨率 resolutio…

記錄:有趣的C#多元運算符 ? : 表達式寫法

有時候用 if //...Whatre you she wanna go else if //...do do do else //...and i know something just like this... 感覺代碼太多了怎么優雅的、高端的替換&#xff1f; 看個高端的栗子菊&#xff1a; LedCOM["parity"] ledData[4] "N" ? …

Study--Oracle-05-Oracler體系結構

一、oracle 體系概覽 Oracle數據庫的體系結構通常包括以下主要組件&#xff1a; 1、實例&#xff08;Instance&#xff09;&#xff1a;運行數據庫的軟件環境&#xff0c;包括內存結構&#xff08;SGA&#xff09;和進程結構&#xff08;Background Processes and User Proces…

Django 一對多關系

1&#xff0c;創建 Django 應用 Test/app9 django-admin startapp app9 2&#xff0c;注冊應用 Test/Test/settings.py 3&#xff0c;添加應用路由 Test/Test/urls.py from django.contrib import admin from django.urls import path, includeurlpatterns [path(admin/,…

《每天5分鐘用Flask搭建一個管理系統》 第10章:前端集成

第10章&#xff1a;前端集成 10.1 前端技術概述 前端技術指的是構建Web應用用戶界面所使用的技術&#xff0c;包括HTML、CSS和JavaScript。現代Web開發中&#xff0c;前端框架如React、Vue.js和Angular等被廣泛使用。 10.2 AJAX與Flask的集成 AJAX&#xff08;Asynchronous…

數據資產安全策略的定制化之道:深入了解各企業獨特需求,量身打造個性化的數據資產保護方案,確保數據安全無虞,助力企業穩健發展

目錄 一、引言 二、企業數據資產安全現狀分析 &#xff08;一&#xff09;數據安全風險多樣化 &#xff08;二&#xff09;傳統安全措施難以滿足需求 &#xff08;三&#xff09;企業數據資產安全意識亟待提高 三、定制化數據資產安全策略的重要性 &#xff08;一&#…

natvicat為什么連不上linux上的mysql?

老規矩&#xff0c;廢話不多說&#xff0c;直接上教程。 號外&#xff0c;數據庫管理工具領域的知名品牌Navicat&#xff0c;推出其免費版本——Navicat Premium Lite&#xff0c;用戶可從Navicat官網下載體驗這款軟件。 https://www.navicat.com.cn/download/navicat-premium-…

【HALCON】如何實現hw窗口自適應相機拍照成像的大小

前言 在開發一個噴碼檢測軟件的時候碰到相機成像和hw窗體的大小不一致&#xff0c;hw太小顯示不完全成像的圖片&#xff0c;這使得成像不均勻&#xff0c;現場辨別起來比較不直觀&#xff0c;因此需要對其進行一個調整。 解決 省略掉讀取圖片的環節&#xff0c;我們只需要將…

別再用this.$forceUpdate()了!—性能優化篇

文章目錄 別再用this.$forceUpdate()了&#xff01;—性能優化篇&#x1f388;介紹&#x1f9e8;弊端注意事項 &#x1f386;解決實例 別再用this.$forceUpdate()了&#xff01;—性能優化篇 起因是接手公司之前外包的項目做項目優化&#xff0c;代碼看著一言難盡&#xff0c;…

CGI面試題及參考答案

什么是CGI?它在Web服務器與應用程序之間扮演什么角色? CGI(Common Gateway Interface) 是一種標準協議,它定義了Web服務器與運行在服務器上的外部程序(通常是腳本或應用程序)之間的通信方式。簡單來說,CGI充當了一個橋梁,使得Web服務器能夠將用戶的請求傳遞給后端程序…

ruoyi—cloud 新建模塊+生成代碼

1.復制一個模塊——修改名字 2.打開模塊下的yml文件&#xff0c;修改端口號和名字 &#xff08;1&#xff09;修改一個名字 &#xff08;2&#xff09;打開yml文件 &#xff08;3&#xff09;修改端口號&#xff0c;不要重復 &#xff08;4&#xff09;改名字和模塊一致 3.…

41、web基礎和http協議

web基礎與http協議 一、web web&#xff1a;就是我們所說得頁面&#xff0c;打開網頁展示得頁面。&#xff08;全球廣域網&#xff0c;萬維網&#xff09; world wide webwww 分布式圖形信息系統 http&#xff1a;超文本傳輸協議 https&#xff1a;加密的超文本傳輸協議…

貓凍干可以天天喂嗎?喂凍干前要了解的必入主食凍干榜單

近年來&#xff0c;凍干貓糧因其高品質而備受喜愛&#xff0c;吸引了無數貓主人的目光&#xff0c;對于像我這樣的養貓達人來說&#xff0c;早已嘗試并認可了凍干喂養。然而&#xff0c;對于初入養貓行列的新手們來說&#xff0c;可能會有疑問&#xff1a;什么是凍干貓糧&#…

Qt——界面優化

目錄 QSS 基本語法 QSS 設置方式 指定控件樣式設置 全局樣式設置 文件加載樣式表 Qt Designer 編輯樣式 選擇器 子控件選擇器 偽類選擇器 樣式屬性 盒模型 控件樣式 按鈕 復選框 單選框 輸入框 列表 菜單欄 登錄界面 繪圖 概念 繪制形狀 繪制線段 繪制…