在虚拟机中部署MinIO

以下的环境为CentOS7!!!

  1. 获取MinIO安装包

    下载地址如下:https://dl.min.io/server/minio/release/linux-amd64/archive/minio-20230809233022.0.0.x86_64.rpm ,通过以下命令可直接将安装包下载至服务器

    1
    wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio-20230809233022.0.0.x86_64.rpm
  2. 安装MinIO

    1
    rpm -ivh minio-20230809233022.0.0.x86_64.rpm
  3. 集成Systemd

    • Systemd概述

      Systemd是一个广泛应用于Linux系统的系统初始化和服务管理器,其可以管理系统中的各种服务和进程,包括启动、停止和重启服务,除此之外,其还可以监测各服务的运行状态,并在服务异常退出时,自动拉起服务,以保证服务的稳定性。系统自带的防火墙服务firewalld,我们自己安装的mysqldredis均是由Systemd进行管理的,此处将MinIO服务也交给Systemd管理。

    • 编写MinIO服务配置文件

      Systemd所管理的服务需要由一个配置文件进行描述,这些配置文件均位于/etc/systemd/system/或者/usr/lib/systemd/system/目录下,下面创建MinIO服务的配置文件。

      执行以下命令创建并打开minio.service文件

      1
      vim /etc/systemd/system/minio.service

      内容如下,具体可参考MinIO官方文档

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      [Unit]
      Description=MinIO
      Documentation=https://min.io/docs/minio/linux/index.html
      Wants=network-online.target
      After=network-online.target
      AssertFileIsExecutable=/usr/local/bin/minio

      [Service]
      WorkingDirectory=/usr/local
      ProtectProc=invisible
      EnvironmentFile=-/etc/default/minio
      ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
      ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES
      Restart=always
      LimitNOFILE=65536
      TasksMax=infinity
      TimeoutStopSec=infinity
      SendSIGKILL=no

      [Install]
      WantedBy=multi-user.target

      注意

      重点关注上述文件中的以下内容即可

      • EnvironmentFile,该文件中可配置MinIO服务所需的各项参数
      • ExecStart,该参数用于配置MinIO服务的启动命令,其中$MINIO_OPTS$MINIO_VOLUMES,均引用于EnvironmentFile中的变量。
        • MINIO_OPTS用于配置MinIO服务的启动选项,可省略不配置。
        • MINIO_VOLUMES用于配置MinIO服务的数据存储路径。
      • Restart,表示自动重启
    • 编写EnvironmentFile文件

      执行以下命令创建并打开/etc/default/minio文件

      1
      vim /etc/default/minio

      内容如下,具体可参考官方文档

      1
      2
      3
      4
      MINIO_ROOT_USER=minioadmin
      MINIO_ROOT_PASSWORD=minioadmin
      MINIO_VOLUMES=/data
      MINIO_OPTS="--console-address :9001"

      注意

      • MINIO_ROOT_USERMINIO_ROOT_PASSWORD为用于访问MinIO的用户名和密码,密码长度至少8位

      • MINIO_VOLUMES用于指定数据存储路径,需确保指定的路径是存在的,可执行以下命令创建该路径。

        1
        mkdir /data
      • MINIO_OPTS中的console-address,用于指定管理页面的地址。

  4. 启动MinIO

    执行以下命令启动MinIO

    1
    systemctl start minio

    执行以下命令查询运行状态
    运行结果信息中,Consloe:http://xxx.xxx.xxx.xxx:xxx 就是访问地址

    1
    systemctl status minio

    设置MinIO开机自启

    1
    systemctl enable minio
  5. 访问MinIO管理页面

    管理页面的访问地址为:http://192.168.10.101:9001

    注意

    ip需要根据你的虚拟机实际情况做出修改,如果按前面的步骤配置的,则端口固定为9001

MinIO快速入门

MinIO核心概念

下面介绍MinIO中的几个核心概念,这些概念在所有的对象存储服务中也都是通用的。

  • 对象(Object)

    对象是实际的数据单元,例如我们上传的一个图片。

  • 存储桶(Bucket)

    存储桶是用于组织对象的命名空间,类似于文件夹。每个存储桶可以包含多个对象。

  • 端点(Endpoint)

    端点是MinIO服务器的网络地址,用于访问存储桶和对象,例如http://192.168.40.101:9000

    注意:

    9000为MinIO的API的默认端口,前边配置的9001以为管理页面端口。

  • Access Key 和 Secret Key

    Access Key是用于标识和验证访问者身份的唯一标识符,相当于用户名。

    Secret Key是与Access Key关联的密码,用于验证访问者的身份。

MinIO管理页面操作

  1. 登录

    管理页面的地址为 http://192.168.40.101:9001 ,登录的用户名和密码为部署时在EnvironmentFile文件中配置的如下参数

    1
    2
    MINIO_ROOT_USER=minioadmin
    MINIO_ROOT_PASSWORD=minioadmin
  2. 创建存储桶
    点击左侧菜单Buckets,再点击右侧CreateBucket

  3. 上传图片

    • 找到目标桶
      点击左侧菜单的ObjectBrowser,在界面中找到并点击目标桶
    • 上传图片
      点击右上角Upload,可以选择上传文件或目录
  4. 访问图片

    • 图片URL
      由于MinIO提供了HTTP访问功能,所以可以通过浏览器直接访问对象。对象URL为MinIO的Endpoint+对象的存储路径,例如下图中的图片对象的URL为 http:192.168.40.101:9000/test/backmom.png
    • 访问权限
      不出意外的话,使用浏览器访问上述URL,会得到如下响应,很显然是没有访问权限。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      <Error>
      <Code>AccessDenied</Code>
      <Message>Access Denied.</Message>
      <Key>backmom.png</Key>
      <BucketName>test</BucketName>
      <Resource>/test/backmom.png</Resource>
      <RequestId>177BC92022FC5684</RequestId>
      <HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId>
      </Error>
      若想继续访问图片,需要修改图片所在桶的访问权限,如下图所示

      如上图所示,可选的访问权限共有三个选项,分别是PrivatePublicCustom,具体说明如下
      • Private
        只允许桶的所有者对该桶进行读写。
      • Public
        允许所有人对该桶进行读写。
      • Custom
        自定义访问权限。
        若想将权限设置为只允许所有者写,但允许所有人读,就需要自定义访问权限。自定义访问权限,需要使用一个规定格式的JSON字符串进行描述,具体格式可参考官方文档
        例如以下JSON字符串表达的含义是:允许(Allow)所有人(*)读取(s3:GetObject)指定桶(test)的所有内容。
        1
        2
        3
        4
        5
        6
        7
        8
        9
        {
        "Statement" : [ {
        "Action" : "s3:GetObject",
        "Effect" : "Allow",
        "Principal" : "*",
        "Resource" : "arn:aws:s3:::test/*"
        } ],
        "Version" : "2012-10-17"
        }
        test桶访问权限设置为Custom,并添加上述内容
        重新访问 http:192.168.40.101:9000/test/backmom.png ,观察是否正常。

MinIO Java SDK

MinIO提供了多种语言的SDK供开发者使用,本项目需要用到Java SDK,下面通过一个简单案例熟悉一下其基本用法,具体内容可参考官方文档

  1. 创建一个maven项目
  2. 引入如下依赖
    1
    2
    3
    4
    5
    <dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.5.3</version>
    </dependency>
  3. 编写如下内容
    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
    public class MinIOQuickstart {

    public static void main(String[] args) {
    //minio节点
    String endpoint = "http://192.168.40.101:9000";
    // 访问密钥
    String accessKey = "minioadmin";
    String secretKey = "minioadmin";

    // 桶名称
    String bucketName = "helllo-minio";
    // 初始化minio客户端,endpoint是节点,credentials参数为accessKey,secretKey
    MinioClient client = MinioClient.builder()
    .endpoint(endpoint)
    .credentials(accessKey, secretKey)
    .build();

    try {
    boolean exists = client.bucketExists(BucketExistsArgs.builder()
    .bucket(bucketName).build());
    //判断桶是否已经存在
    if(!exists){
    //创建桶, 这里的bucketName是桶名称
    client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());

    // 桶策略(访问权限)
    String policy= """
    {
    "Statement" : [ {
    "Action" : "s3:GetObject",
    "Effect" : "Allow",
    "Principal" : "*",
    "Resource" : "arn:aws:s3:::%s/*"
    } ],
    "Version" : "2012-10-17"
    }
    """.formatted(bucketName);

    // 设置桶策略, 这里的bucketName是桶名称, 这里的policy是桶策略
    client.setBucketPolicy(SetBucketPolicyArgs.builder()
    .bucket(bucketName).config(policy).build());

    }

    // 上传文件 filename是文件路径, bucketName是桶名称, objectName是对象(在桶中文件的)名称
    client.uploadObject(UploadObjectArgs.builder().
    filename("C:\\Users\\xnj\\Pictures\\保存的图片\\loong.jpg")
    .bucket(bucketName).object("long.jpg").build());

    System.out.println("上传成功");
    } catch (Exception e) {
    e.printStackTrace();
    }


    }
    }
  4. 运行测试
    运行上述代码,然后查看MinIO管理页面,观察是否上传成功。

第三方工具推件:X-File-Storage

  1. 介绍
    一行代码将文件存储到本地、FTP、SFTP、WebDAV、阿里云 OSS、华为云 OBS、七牛云 Kodo、腾讯云 COS、百度云 BOS、又拍云 USS、MinIO、 Amazon S3、GoogleCloud Storage、FastDFS、 Azure Blob Storage、Cloudflare R2、金山云 KS3、美团云 MSS、京东云 OSS、天翼云 OOS、移动 云EOS、沃云 OSS、 网易数帆 NOS、Ucloud US3、青云 QingStor、平安云 OBS、首云 OSS、IBM COS、其它兼容 S3 协议的存储平台。

  2. 官网:
    中文官网:https://x-file-storage.xuyanwu.cn/#/
    下面的快速入门-以上面minio为例,更多参考官网

  3. 引入依赖,默认为springboot环境

    • 引入x-file-storage-spring的maven依赖
      1
      2
      3
      4
      5
      <dependency>
      <groupId>org.dromara.x-file-storage</groupId>
      <artifactId>x-file-storage-spring</artifactId>
      <version>2.2.1</version>
      </dependency>
    • 引入对应平台依赖,没有则不引,这里为minio
      1
      2
      3
      4
      5
      <dependency>
      <groupId>io.minio</groupId>
      <artifactId>minio</artifactId>
      <version>8.5.2</version>
      </dependency>
  4. 配置文件
    以下方配置文件为例,注意补充密钥等参数
    上传文件一个test.png的图片
    最终路径为:http://192.168.40.101:9000/dkd-oss/dkd-images/test.png

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 文件上传
    dromara:
    x-file-storage: #文件存储配置
    default-platform: minio-1 #默认使用的存储平台
    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
    minio:
    - platform: minio-1 # 存储平台标识
    enable-storage: true # 启用存储
    access-key:
    secret-key:
    end-point: http://192.168.40.101:9000
    bucket-name: dkd-oss
    domain: http://192.168.40.101:9000/dkd-oss/ # 访问域名,注意“/”结尾,例如:http:// minio.abc.com/abc/
    base-path: dkd-images/ # 基础路径
  5. 编码

    • 在启动类上加上@EnableFileStorage注解
  6. 上传文件

    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
    @RestController
    public class FileDetailController {

    @Autowired
    private FileStorageService fileStorageService;//注入实列

    /**
    * 上传文件
    */
    @PostMapping("/upload")
    public FileInfo upload(MultipartFile file) {
    return fileStorageService.of(file).upload();
    }

    /**
    * 上传文件,成功返回文件 url
    */
    @PostMapping("/upload2")
    public String upload2(MultipartFile file) {
    FileInfo fileInfo = fileStorageService.of(file)
    .setPath("upload/") //保存到相对路径下,为了方便管理,不需要可以不写
    .setSaveFilename("image.jpg") //设置保存的文件名,不需要可以不写,会随机生成
    .setObjectId("0") //关联对象id,为了方便管理,不需要可以不写
    .setObjectType("0") //关联对象类型,为了方便管理,不需要可以不写
    .putAttr("role","admin") //保存一些属性,可以在切面、保存上传记录、自定义存储平 台等地方获取使用,不需要可以不写
    .upload(); //将文件上传到对应地方
    return fileInfo == null ? "上传失败!" : fileInfo.getUrl();
    }

    /**
    * 上传图片,成功返回文件信息
    * 图片处理使用的是 https://github.com/coobird/thumbnailator
    */
    @PostMapping("/upload-image")
    public FileInfo uploadImage(MultipartFile file) {
    return fileStorageService.of(file)
    .image(img -> img.size(1000,1000)) //将图片大小调整到 1000*1000
    .thumbnail(th -> th.size(200,200)) //再生成一张 200*200 的缩略图
    .upload();
    }

    /**
    * 上传文件到指定存储平台,成功返回文件信息
    */
    @PostMapping("/upload-platform")
    public FileInfo uploadPlatform(MultipartFile file) {
    return fileStorageService.of(file)
    .setPlatform("aliyun-oss-1") //使用指定的存储平台
    .upload();
    }

    /**
    * 直接读取 HttpServletRequest 中的文件进行上传,成功返回文件信息
    * 使用这种方式有些注意事项,请查看文档 基础功能-上传 章节
    */
    @PostMapping("/upload-request")
    public FileInfo uploadPlatform(HttpServletRequest request) {
    return fileStorageService.of(request).upload();
    }
    }