使用docker-compose部署Minio,并整合Spring boot实现文件上传

本文详细描述了如何在CentOS7.9环境中安装Docker和Docker-compose,配置Minio对象存储服务,并通过Nginx反向代理实现SpringBoot应用的文件上传功能,包括设置环境、安装步骤和配置代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

部署环境

centos7.9搭建

使用vnware16安装centos7.9系统https://blog.youkuaiyun.com/andyLyysh/article/details/127248551?spm=1001.2014.3001.5502

Docker、Docker-compose 安装

docker、docker-compose 安装https://blog.youkuaiyun.com/andyLyysh/article/details/126738190?spm=1001.2014.3001.5502

Minio安装

docker-compose文件配置

在centos系统中创建minio目录,将docker-compose.yaml文件放在minio目录下。

version: "3"

services:
  minio:
    image: quay.io/minio/minio
    container_name: minio
    hostname: minio
    privileged: true
    restart: always
    environment:
      TZ: Asia/Shanghai
      # 账号
      MINIO_ROOT_USER: topfus
      # 密码
      MINIO_ROOT_PASSWORD: topfus123
    ports:
      - 9000:9000
      - 9090:9090
    volumes: 
      - ./minio/data:/data
      - ./minio/config:/root/.minio
    command: server /data --console-address ":9090"
    networks:
      minio-network:
        ipv4_address: 172.28.0.5

networks:
  minio-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.28.0.0/24
    name: minio-network

运行

docker-compose up -d

Minio使用Nginx反向代理

nginx配置

upstream minio_server {
    least_conn; # 表示将请求传递给活跃度最低的server
    server 127.0.0.1:9000;
}

upstream minio_console {
    least_conn;
    server 127.0.0.1:9090;
}

server {
    # listen 443 ssl;
    listen       80;
    listen  [::]:80;
    server_name server.example.com;
    charset utf-8;

    client_max_body_size 1024m;     # 上传文件大小限制,默认是1M
    client_body_buffer_size 300k;   # 数据流传输大小

    # ssl_certificate      /data/minio/ssl/server.example.com.pem;
    # ssl_certificate_key  /data/minio/ssl/server.example.com.key;

    # ssl_session_timeout  10m;
    # ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    # ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    # ssl_prefer_server_ciphers  on;

    ignore_invalid_headers off;     # 标头中允许特殊字符

    # 禁用缓冲
    proxy_buffering off;
    proxy_request_buffering off;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 300;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        chunked_transfer_encoding off;

        proxy_pass http://minio_server/;
    }
}

server {
    listen       80;
    listen  [::]:80;
    server_name  console.example.com;

    # 标头中允许特殊字符
    ignore_invalid_headers off;

    client_max_body_size 1024m;     # 上传文件大小限制,默认是1M
    client_body_buffer_size 300k;   # 数据流传输大小

    # 禁用缓冲
    proxy_buffering off;
    proxy_request_buffering off;

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-NginX-Proxy true;

        # 这是传递要哈希的正确 IP 所必需的
        # 注意:这个配置需要安装http_realip_module模块
        real_ip_header X-Real-IP;

        proxy_connect_timeout 300;

        # 支持websocket
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        chunked_transfer_encoding off;

        proxy_pass http://minio_console/;
    }
}

安装realip模块

./configure --prefix=/usr/local/nginx --with-http_stub_status_module  --with-pcre=../pcre-6.6 --with-http_realip_module

make

make install

以上nginx配置好后,直接访问域名console.example.com后会跳转console.example.com:9090,如图:
在这里插入图片描述

整合Spring Boot实现文件上传

引入Minio依赖包

<!-- https://mvnrepository.com/artifact/io.minio/minio -->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.5.7</version>
</dependency>

创建配置文件

application.yml配置

minio:
  bucketname: zhush-bucket
  endpoint: http://127.0.0.1:9000/
  accesskey: minioadmin
  secretkey: minioadmin

创建MinioConfig配置类

package com.zhush.service.config;

import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @ClassName MinioConfig
 * @Description TODO
 * @Author zhush
 * @Date 2023/12/27 0027 9:52
 **/
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {

    private String bucketname;

    private String endpoint;

    private String accesskey;

    private String secretkey;

    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accesskey, secretkey)
                .build();
    }

}

封装MinioUtils工具类

package com.zhush.service.utils;

import cn.hutool.core.date.DateUtil;
import com.zhush.service.config.MinioConfig;
import io.minio.*;
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 jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

/**
 * @ClassName MinioUtils
 * @Description minio对象存储工具类
 * @Author zhush
 * @Date 2023/12/27 0027 9:54
 **/
@Slf4j
@Component
public class MinioUtils {

    @Resource
    private MinioConfig minioConfig;

    @Resource
    private MinioClient minioClient;

    /**
     * 创建
     * @param bucketName
     */
    @SneakyThrows
    public void makeBucketName(String bucketName) {
        minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 删除
     * @param bucketName
     */
    @SneakyThrows
    public void removeBucketName(String bucketName) {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 验证是否存在
     * @param bucketName
     * @return
     */
    @SneakyThrows
    public Boolean bucketExists(String bucketName) {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**
     * 获取bucket列表
     * @return
     */
    @SneakyThrows
    public List<Bucket> getBucketList() {
        return minioClient.listBuckets();
    }

    /**
     * 文件上传
     * @param file
     * @return 返回文件路径
     */
    @SneakyThrows
    public String upload(MultipartFile file) {
        // 获取上传文件名称
        String originalFilename = file.getOriginalFilename();
        // 根据年月日创建data_dir
        String dataDir = DateUtil.format(new Date(), "yyyyMMdd");
        // 使用uuid生成新的文件名称
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String fileName = dataDir + "/" + uuid + originalFilename;
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(minioConfig.getBucketname())
                .object(fileName)
                .stream(file.getInputStream(), file.getSize(), -1)
                .build());
        return minioConfig.getEndpoint() + "/" + minioConfig.getBucketname() + "/" + fileName;
    }

    /**
     * 批量文件上传
     * @param files
     * @return
     */
    @SneakyThrows
    public List<String> uploads(MultipartFile[] files) {
        List<String> fileUrls = new ArrayList<>();
        for (MultipartFile file : files) {
            // 获取上传文件名称
            String originalFilename = file.getOriginalFilename();
            // 根据年月日创建data_dir
            String dataDir = DateUtil.format(new Date(), "yyyyMMdd");
            // 使用uuid生成新的文件名称
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            String fileName = dataDir + "/" + uuid + originalFilename;
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioConfig.getBucketname())
                    .object(fileName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .build());
            String fileUrl = minioConfig.getEndpoint() + "/" + minioConfig.getBucketname() + "/" + fileName;
            fileUrls.add(fileUrl);
        }
        return fileUrls;
    }

    /**
     * 预览
     * @param fileName
     * @return
     */
    @SneakyThrows
    public String preview(String fileName) {
        return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                .bucket(minioConfig.getBucketname())
                .object(fileName)
                .method(Method.GET)
                .build());
    }

    /**
     * 下载
     * @param fileName
     * @param response
     */
    @SneakyThrows
    public void download(String fileName, HttpServletResponse response) {
        GetObjectResponse objectResponse = minioClient.getObject(GetObjectArgs.builder()
                .bucket(minioConfig.getBucketname())
                .object(fileName)
                .build());
        byte[] bytes = new byte[1024];
        int len;
        FastByteArrayOutputStream outputStream = new FastByteArrayOutputStream();
        while ((len = objectResponse.read(bytes)) != -1) {
            outputStream.write(bytes, 0, len);
        }
        outputStream.close();
        byte[] byteArray = outputStream.toByteArray();
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/force-download"); // 设置强制下载不打开
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
        ServletOutputStream stream = response.getOutputStream();
        stream.write(byteArray);
        stream.flush();
    }



    /**
     * 获取文件对象
     * @return
     */
    @SneakyThrows
    public List<Item> getItemObjects() {
        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
                .bucket(minioConfig.getBucketname())
                .build());
        List<Item> items = new ArrayList<>();
        for (Result<Item> item : results) {
            items.add(item.get());
        }
        return items;
    }

    /**
     * 删除文件
     * @param fileName
     */
    @SneakyThrows
    public void removeFile(String fileName) {
        minioClient.removeObject(RemoveObjectArgs.builder()
                .bucket(minioConfig.getBucketname())
                .object(fileName)
                .build());
    }

    /**
     * 批量删除文件
     * @param fileNameList
     */
    @SneakyThrows
    public void removeFiles(List<String> fileNameList) {
        List<DeleteObject> deleteObjects = new LinkedList<>();
        for (String objectName : fileNameList) {
            deleteObjects.add(new DeleteObject(objectName));
        }
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder()
                .bucket(minioConfig.getBucketname())
                .objects(deleteObjects)
                .build());
        for (Result<DeleteError> result : results) {
            DeleteError error = result.get();
            log.error("Error in deleting object " + error.objectName() + "; " + error.message());
        }
    }
}

### 使用 Docker Compose 部署 MinIO 的教程 #### 准备工作 为了确保环境准备就绪,在开始前需确认已成功安装配置好 `Docker` 和 `docker-compose` 工具。对于 CentOS 用户而言,可能需要先移除旧版 Docker 及其关联组件以避免冲突[^1]。 ```bash yum remove docker docker-common docker-selinux docker-engine ``` 接着赋予 `/usr/local/bin/docker-compose` 文件执行权限以便后续操作能够顺利进行[^2]: ```bash chmod +x /usr/local/bin/docker-compose ``` #### 创建项目目录结构 建议创建一个新的文件夹来存放所有的配置文件和服务定义,比如命名为 `minio-deployment`: ```bash mkdir -p ~/minio-deployment && cd ~/minio-deployment ``` 在此路径下初始化所需的子目录用于存储数据卷和其他资源: ```bash mkdir data config logs ``` #### 编写 `docker-compose.yml` 接下来编写 `docker-compose.yml` 来描述服务架构以及各容器间的依赖关系。下面是一个简单的例子展示如何启动单节点MinIO实例;实际生产环境中推荐构建多节点高可用集群。 ```yaml version: '3' services: minio: image: minio/minio ports: - "9000:9000" - "9001:9001" environment: MINIO_ROOT_USER: ${MINIO_ACCESS_KEY} MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY} volumes: - ./data:/data - ./config:/root/.minio command: server /data --console-address ":9001" ``` 此配置通过端口映射使得外部可以访问到 MinIO 提供的对象存储 API (默认监听于 9000),同时也开放了管理控制台(位于 9001)。 #### 设置环境变量 考虑到安全性因素,通常不会直接把敏感信息硬编码进 YAML 文件里而是采用 `.env` 文件的形式加载这些参数值。在同一级目录内新建名为`.env`的纯文本文件将如下两行加入其中替换为你自己的密钥组合: ``` MINIO_ACCESS_KEY=your-access-key-here MINIO_SECRET_KEY=your-secret-key-here ``` #### 启动服务 完成上述准备工作之后就可以利用命令让整个应用栈跑起来了: ```bash docker-compose up -d ``` 这会拉取必要的镜像、建立网络连接且按照指定的方式运行各个组成部分。此时应该可以在浏览器地址栏输入 http://localhost:9001 访问 MinIO Web 控制面板界面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

珍朱(珠)奶茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值