我的编程空间,编程开发者的网络收藏夹
学习永远不晚

分布式对象存储服务minio安装和部署

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

分布式对象存储服务minio安装和部署

一、服务器安装minio

 

1.进行下载

下载地址:

https://dl.min.io/server/minio/release/linux-amd64/minio

2.新建minio安装目录,执行如下命令

mkdir -p /home/minio/data

把二进制文件上传到安装目录后,执行:


chmod +x minio    //给予权限

//注意:以前的老版本minio的配置中,配置用户名和密码时,是这两个参数:

MINIO_ACCESS_KEY 和MINIO_SECRET_KEY

而现在比较新的版本的minio,需要替换成MINIO_ROOT_USER和MINIO_ROOT_PASSWORD

export MINIO_ROOT_USER=fsp-manage

export MINIO_ROOT_PASSWORD=springboot-fsp-manage


./minio server /home/minio/data        //启动

 后台启动,并打印日志

自定义端口方式:自定义启动端口号以及控制台端口号,不设置则控制台会自动配置其他端口号,非常不方便

nohup ./minio server  --address :9000 --console-address :9001 /home/minio/data > /home/minio/data/minio.log &
ps -ef|grep minio

二、进行访问,并设置桶

        地址:http://127.0.0.1:9000

 三、springboot进行实现

1.引入依赖

!-- minio 相关依赖 -->    io.minio    minio    3.0.10    com.alibaba    fastjson    1.2.51    org.springframework.boot    spring-boot-starter-thymeleaf

 2.在 application.yml 文件中加入 MinIO 服务器的相关信息

minio:  endpoint: http://serverip  port: 9002  accessKey: fsp-manage  secretKey: springboot-fsp-manage  bucketName: fsp-dev  secure: false

3.创建实体类

这一步,我们将配置文件中 minio 的配置信息通过注解的方式注入到 MinioProp 这个实体中,方便后面我们使用

package com.xiaomifeng1010.minio.configuration; import io.minio.MinioClient;import io.minio.errors.InvalidPortException;import lombok.Getter;import lombok.Setter;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.stereotype.Component; @Configuration@Component@ConfigurationProperties(prefix = "minio")@Getter@Setterpublic class MinioConfig {    private String endpoint;    private int port;    private String accessKey;    private String secretKey;    private Boolean secure;    private String bucketName;     @Bean    public MinioClient getMinioClient() throws InvalidPortException {        MinioClient minioClient = MinioClient.builder().endpoint(endpoint, port, secure)                .credentials(accessKey, secretKey)                .build();        return minioClient;    }////    @Bean(name = "multipartResolver")//    public MultipartResolver multipartResolver(){//        CommonsMultipartResolver resolver = new CommonsMultipartResolver();//        resolver.setDefaultEncoding("UTF-8");//        //resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常//        resolver.setResolveLazily(true);//        resolver.setMaxInMemorySize(40960);//        //上传文件大小 50M 50*1024*1024//        resolver.setMaxUploadSize(50*1024*1024);//        return resolver;//    }}

如何你要配置ip和port在同一个参数中,不分开,或者是直接配置域名(域名映射了ip和port),那么配置的yml 修改如下:

 

把port注释掉,同时配置类也修改一下就可以了:

 

5、上传工具类

package com.xiaomifeng.minio.util; import io.minio.*;import io.minio.errors.*;import io.minio.http.Method;import io.minio.messages.Bucket;import io.minio.messages.DeleteError;import io.minio.messages.DeleteObject;import io.minio.messages.Item;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang.StringUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.InputStream;import java.nio.charset.StandardCharsets;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.util.ArrayList;import java.util.List; @Component@Slf4jpublic class MinioClientUtils {     @Autowired    private MinioClient minioClient;     private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600;         public boolean bucketExists(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        boolean flag = false;        flag = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());        if (flag) {            return true;        }        return false;    }         public boolean makeBucket(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, RegionConflictException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        boolean flag = bucketExists(bucketName);        if (!flag) {            minioClient.makeBucket(                    MakeBucketArgs.builder().bucket(bucketName).build());            return true;        } else {            return false;        }    }         public List listBucketNames() throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {        List bucketList = listBuckets();        List bucketListName = new ArrayList<>();        for (Bucket bucket : bucketList) {            bucketListName.add(bucket.name());        }        return bucketListName;    }         public List listBuckets() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        return minioClient.listBuckets();    }         public boolean removeBucket(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        boolean flag = bucketExists(bucketName);        if (flag) {            Iterable> myObjects = listObjects(bucketName);            for (Result result : myObjects) {                Item item = result.get();                // 有对象文件,则删除失败                if (item.size() > 0) {                    return false;                }            }            // 删除存储桶,注意,只有存储桶为空时才能删除成功。            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());            flag = bucketExists(bucketName);            if (!flag) {                return true;            }         }        return false;    }         public List listObjectNames(String bucketName) throws XmlParserException, IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, InvalidBucketNameException, InsufficientDataException, InternalException {        List listObjectNames = new ArrayList<>();        boolean flag = bucketExists(bucketName);        if (flag) {            Iterable> myObjects = listObjects(bucketName);            for (Result result : myObjects) {                Item item = result.get();                listObjectNames.add(item.objectName());            }        }        return listObjectNames;    }         public Iterable> listObjects(String bucketName) throws XmlParserException, IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, InvalidBucketNameException, InsufficientDataException, InternalException {        boolean flag = bucketExists(bucketName);        if (flag) {            return minioClient.listObjects( ListObjectsArgs.builder().bucket(bucketName).build());        }        return null;    }         public boolean uploadObject(String bucketName, String objectName, String fileName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        boolean flag = bucketExists(bucketName);        if (flag) {            minioClient.uploadObject(                    UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build());            ObjectStat statObject = statObject(bucketName, objectName);            if (statObject != null && statObject.length() > 0) {                return true;            }        }        return false;     }         public void putObject(String bucketName, MultipartFile multipartFile, String filename) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);        putObjectOptions.setContentType(multipartFile.getContentType());        minioClient.putObject(                PutObjectArgs.builder().bucket(bucketName).object(filename).stream(                        multipartFile.getInputStream(), multipartFile.getSize(), -1).contentType(multipartFile.getContentType())                        .build());    }         public boolean putObject(String bucketName, String objectName, InputStream inputStream,String contentType) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {        boolean flag = bucketExists(bucketName);        if (flag) {            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(                    //不清楚文件的大小时,可以传-1,10485760。如果知道大小也可以传入size,partsize。                    inputStream,  -1, 10485760)                    .contentType(contentType)                    .build());            ObjectStat statObject = statObject(bucketName, objectName);            if (statObject != null && statObject.length() > 0) {                return true;            }        }        return false;    }         public InputStream getObject(String bucketName, String objectName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        boolean flag = bucketExists(bucketName);        if (flag) {            ObjectStat statObject = statObject(bucketName, objectName);            if (statObject != null && statObject.length() > 0) {                InputStream stream = minioClient.getObject( GetObjectArgs.builder()                        .bucket(bucketName)                        .object(objectName)                        .build());                return stream;            }        }        return null;    }         public InputStream getObject(String bucketName, String objectName, long offset, Long length) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        boolean flag = bucketExists(bucketName);        if (flag) {            ObjectStat statObject = statObject(bucketName, objectName);            if (statObject != null && statObject.length() > 0) {                InputStream stream = minioClient.getObject(  GetObjectArgs.builder()                        .bucket(bucketName)                        .object(objectName)                        .offset(1024L)                        .length(4096L)                        .build());                return stream;            }        }        return null;    }         public boolean downloadObject(String bucketName, String objectName, String fileName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        boolean flag = bucketExists(bucketName);        if (flag) {            ObjectStat statObject = statObject(bucketName, objectName);            if (statObject != null && statObject.length() > 0) {                minioClient.downloadObject(DownloadObjectArgs.builder()                        .bucket(bucketName)                        .object(objectName)                        .filename(fileName)                        .build());                return true;            }        }        return false;    }         public boolean removeObject(String bucketName, String objectName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        boolean flag = bucketExists(bucketName);        if (flag) {            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());            return true;        }        return false;    }         public List removeObjects(String bucketName, List objectNames) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {        List deleteErrorNames = new ArrayList<>();        boolean flag = bucketExists(bucketName);        if (flag) {            Iterable> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objectNames).build());            for (Result result : results) {                DeleteError error = result.get();                deleteErrorNames.add(error.objectName());            }        }        return deleteErrorNames;    }         public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws InvalidExpiresRangeException, IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {        boolean flag = bucketExists(bucketName);        String url = "";        if (flag) {            if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {                throw new InvalidExpiresRangeException(expires,                        "expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);            }            try {                url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()                        .method(Method.GET)                        .bucket(bucketName)                        .object(objectName)                        .expiry(expires)//动态参数                        //                       .expiry(24 * 60 * 60)//用秒来计算一天时间有效期//                        .expiry(1, TimeUnit.DAYS)//按天传参//                        .expiry(1, TimeUnit.HOURS)//按小时传参数                        .build());            } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidBucketNameException | InvalidExpiresRangeException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {                e.printStackTrace();            }        }        return url;    }         public String presignedPutObject(String bucketName, String objectName, Integer expires) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {        boolean flag = bucketExists(bucketName);        String url = "";        if (flag) {            if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {                try {                    throw new InvalidExpiresRangeException(expires,"expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);                } catch (InvalidExpiresRangeException e) {                    e.printStackTrace();                }            }            try {                url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()                        .method(Method.PUT)                        .bucket(bucketName)                        .object(objectName)                        .expiry(expires)//动态参数                        //                       .expiry(24 * 60 * 60)//用秒来计算一天时间有效期//                        .expiry(1, TimeUnit.DAYS)//按天传参//                        .expiry(1, TimeUnit.HOURS)//按小时传参数                        .build());            } catch (ErrorResponseException | InsufficientDataException e) {                e.printStackTrace();            } catch (InternalException e) {                log.error("InternalException",e);            } catch (InvalidBucketNameException e) {                log.error("InvalidBucketNameException",e);            } catch (InvalidExpiresRangeException e) {                log.error("InvalidExpiresRangeException",e);            } catch (InvalidKeyException e) {                log.error("InvalidKeyException",e);            } catch (InvalidResponseException e) {                log.error("InvalidResponseException",e);            } catch (IOException e) {                log.error("IOException",e);            } catch (NoSuchAlgorithmException e) {                log.error("NoSuchAlgorithmException",e);            } catch (ServerException e) {                log.error("ServerException",e);            } catch (XmlParserException e) {                log.error("XmlParserException",e);            }        }        return url;    }         public ObjectStat statObject(String bucketName, String objectName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {        boolean flag = bucketExists(bucketName);        if (flag) {            ObjectStat statObject = null;            try {                statObject = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());            } catch (ErrorResponseException e) {                log.error("ErrorResponseException",e);            } catch (InsufficientDataException e) {                log.error("ErrorResponseException",e);                e.printStackTrace();            } catch (InternalException e) {                log.error("InternalException",e);            } catch (InvalidBucketNameException e) {                log.error("InvalidBucketNameException",e);            } catch (InvalidKeyException e) {                log.error("InvalidKeyException",e);            } catch (InvalidResponseException e) {                log.error("InvalidResponseException",e);            } catch (IOException e) {                log.error("IOException",e);            } catch (NoSuchAlgorithmException e) {                log.error("NoSuchAlgorithmException",e);            } catch (ServerException e) {                log.error("ServerException",e);            } catch (XmlParserException e) {                log.error("XmlParserException",e);            }            return statObject;        }        return null;    }         public String getObjectUrl(String bucketName, String objectName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {        boolean flag = bucketExists(bucketName);        String url = "";        if (flag) {            try {                url = minioClient.getObjectUrl(bucketName, objectName);            } catch (ErrorResponseException e) {                log.error("XmlParserException",e);            } catch (InsufficientDataException e) {                log.error("InsufficientDataException",e);            } catch (InternalException e) {                log.error("InternalException",e);            } catch (InvalidBucketNameException e) {                log.error("InvalidBucketNameException",e);            } catch (InvalidKeyException e) {                log.error("InvalidKeyException",e);            } catch (InvalidResponseException e) {                log.error("InvalidResponseException",e);            } catch (IOException e) {                log.error("IOException",e);            } catch (NoSuchAlgorithmException e) {                log.error("NoSuchAlgorithmException",e);            } catch (ServerException e) {                log.error("ServerException",e);            } catch (XmlParserException e) {                log.error("XmlParserException",e);            }        }        return url;    }       public void downloadFile(String bucketName, String fileName, String originalName, HttpServletResponse response) {        try {             InputStream file = minioClient.getObject(GetObjectArgs.builder()                    .bucket(bucketName)                    .object(fileName)                    .build());            String filename = new String(fileName.getBytes("ISO8859-1"), StandardCharsets.UTF_8);            if (StringUtils.isNotEmpty(originalName)) {                fileName = originalName;            }            response.setHeader("Content-Disposition", "attachment;filename=" + filename);            ServletOutputStream servletOutputStream = response.getOutputStream();            int len;            byte[] buffer = new byte[1024];            while ((len = file.read(buffer)) > 0) {                servletOutputStream.write(buffer, 0, len);            }            servletOutputStream.flush();            file.close();            servletOutputStream.close();        } catch (ErrorResponseException e) {            log.error("ErrorResponseException",e);        } catch (Exception e) {            log.error("Exception",e);        }    }}

6.controller接口

package com.dcboot.module.minio.controller; import cn.hutool.core.io.FileUtil;import com.dcboot.base.util.ApiResult;import com.dcboot.module.minio.configuration.MinioConfig;import com.dcboot.module.minio.dto.response.MinioResponseDTO;import com.dcboot.module.minio.entity.MinioFile;import com.dcboot.module.util.MinioClientUtils;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiOperation;import lombok.AllArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.apache.commons.collections4.CollectionUtils;import org.apache.commons.lang3.RandomStringUtils;import org.apache.commons.lang3.math.NumberUtils;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;import org.springframework.web.multipart.MultipartFile; import java.io.FileInputStream;import java.time.Instant;import java.util.ArrayList;import java.util.List; @Controller@RequestMapping("/fileHandle")@Slf4j@AllArgsConstructor@Api(tags = "文件处理模块")public class FileHandleController {     private MinioClientUtils minioClientUtils;     private MinioConfig minioConfig;     @PostMapping(value = {"/admin/uploadFile","/web/uploadFile"})    @ResponseBody    @ApiOperation(value = "上传文件,支持批量上传")    @ApiImplicitParam(name = "files",value = "文件对象",dataType = "File")    public ApiResult uploadFile(@RequestParam("files") List files) {        log.info(files.toString());        if (CollectionUtils.isEmpty(files)){            return ApiResult.error("未选择文件!");        }         List MinioResponseDTOList=new ArrayList<>();        for (MultipartFile file : files) {            String originalFilename = file.getOriginalFilename();//            获取文件拓展名            String extName = FileUtil.extName(originalFilename);            log.info("文件拓展名:"+extName);//            生成新的文件名,存入到minio            long millSeconds = Instant.now().toEpochMilli();            String minioFileName=millSeconds+ RandomStringUtils.randomNumeric(12)+"."+extName;            String contentType = file.getContentType();            log.info("文件mime:{}",contentType);//            返回文件大小,单位字节            long size = file.getSize();            log.info("文件大小:"+size);            try {                String bucketName = minioConfig.getBucketName();                minioClientUtils.putObject(bucketName,file,minioFileName);                String fileUrl = minioClientUtils.getObjectUrl(bucketName, minioFileName);                MinioFile minioFile = new MinioFile();                minioFile.setOriginalFileName(originalFilename);                minioFile.setFileExtName(extName);                minioFile.setFileName(minioFileName);                minioFile.setFileSize(size);                minioFile.setMime(contentType);                minioFile.setIsDelete(NumberUtils.INTEGER_ZERO);                minioFile.setFileUrl(fileUrl);                boolean insert = minioFile.insert();                if (insert) {                    MinioResponseDTO minioResponseDTO = new MinioResponseDTO();                    minioResponseDTO.setFileId(minioFile.getId());                    minioResponseDTO.setOriginalFileName(originalFilename);                    minioResponseDTO.setFileUrl(fileUrl);                    MinioResponseDTOList.add(minioResponseDTO);                }               } catch (Exception e) {                log.error("上传文件出错:{}",e);                return ApiResult.error("上传文件出错");             }        }         return ApiResult.success(MinioResponseDTOList);    }          @GetMapping("/test")    @ApiOperation(value = "测试minio文件上传")    public ApiResult testPutObject() throws Exception {        FileInputStream fileInputStream = new FileInputStream("C:\\Users\\MSI\\Desktop\\新建文本文档.txt");        boolean bs = minioClientUtils.putObject("fsp-dev", "新建文本文档.txt", fileInputStream, "image/jpg");        log.info("上传成功?"+bs);        return ApiResult.success("上传成功");    }  }

删除文件:

 //文件删除    @DeleteMapping    public String delete(String name) {        try {            MinioClient minioClient = new MinioClient(ENDPOINT, ACCESSKEY, SECRETKEY);            minioClient.removeObject(BUCKETNAME, name);        } catch (Exception e) {            return "删除失败"+e.getMessage();        }        return "删除成功";    }

来源地址:https://blog.csdn.net/weixin_59244784/article/details/130246017

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

分布式对象存储服务minio安装和部署

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Docker部署MinIO对象存储服务器结合Cpolar实现远程访问

🔥博客主页: 小羊失眠啦. 🎥系列专栏:《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞👍收藏⭐评论✍️ 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣
Docker部署MinIO对象存储服务器结合Cpolar实现远程访问
2023-12-22

Docker部署MinIO对象存储服务器结合内网穿透实现远程访问

文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对
Docker部署MinIO对象存储服务器结合内网穿透实现远程访问
2023-12-22

编程热搜

目录