当前位置:首页 > 技术 > 正文内容

基于Docker部署MinIO并在Spring Boot中集成对象存储服务

访客 技术 2026年6月28日 2

容器化部署MinIO服务端

镜像获取与准备

从官方仓库获取最新稳定版镜像:

docker pull minio/minio:latest

数据持久化配置

创建宿主机目录用于映射容器内的存储与配置:

mkdir -p /opt/minio/{storage,config}

服务启动参数

执行以下命令启动容器,注意端口映射与环境变量配置:

docker run -d \
  --name minio-server \
  --restart=unless-stopped \
  -p 9000:9000 \
  -p 9090:9090 \
  -v /opt/minio/storage:/data \
  -v /opt/minio/config:/root/.minio \
  -e MINIO_ROOT_USER=admin \
  -e MINIO_ROOT_PASSWORD=SecurePass123 \
  minio/minio server /data --console-address ":9090"

参数说明:

  • 9000:S3 API服务端口
  • 9090:Web管理控制台端口
  • MINIO_ROOT_USER:管理员账号
  • MINIO_ROOT_PASSWORD:管理员密码(需8位以上)

访问验证

浏览器打开 http://服务器IP:9090,使用配置的账号密码登录管理界面。

自启设置

docker update --restart=always minio-server

Spring Boot工程集成

依赖引入

pom.xml中添加必要组件:

<dependencies>
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.5.7</version>
    </dependency>
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.12.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
    </dependency>
</dependencies>

配置属性类

定义YAML配置映射:

@Data
@Component
@ConfigurationProperties(prefix = "oss.minio")
public class MinioServerProps {
    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String defaultBucket;
}

客户端初始化

@Configuration
public class MinioClientFactory {

    @Autowired
    private MinioServerProps serverProps;

    @Bean
    public MinioClient createClient() {
        return MinioClient.builder()
                .endpoint(serverProps.getEndpoint())
                .credentials(serverProps.getAccessKey(), serverProps.getSecretKey())
                .build();
    }
}

业务实现层

文件元信息封装:

@Data
public class ObjectMeta {
    private String objectKey;
    private Long size;
    private LocalDateTime lastModified;
    private Boolean isFolder;
}

核心服务实现:

@Service
public class StorageServiceImpl implements StorageService {

    @Autowired
    private MinioClient minioClient;
    @Autowired
    private MinioServerProps serverProps;

    @Override
    public List<ObjectMeta> listObjects(String prefix) {
        List<ObjectMeta> result = new ArrayList<>();
        try {
            Iterable<Result<Item>> objects = minioClient.listObjects(
                    ListObjectsArgs.builder()
                            .bucket(serverProps.getDefaultBucket())
                            .prefix(prefix)
                            .recursive(true)
                            .build());
            
            for (Result<Item> itemResult : objects) {
                Item item = itemResult.get();
                ObjectMeta meta = new ObjectMeta();
                meta.setObjectKey(item.objectName());
                meta.setSize(item.size());
                meta.setLastModified(item.lastModified().toLocalDateTime());
                meta.setIsFolder(item.isDir());
                result.add(meta);
            }
        } catch (Exception e) {
            throw new RuntimeException("列举对象失败", e);
        }
        return result;
    }

    @Override
    public String uploadStream(MultipartFile file, String category) {
        String originalName = file.getOriginalFilename();
        String ext = originalName.substring(originalName.lastIndexOf("."));
        String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        String key = String.format("%s/%s/%s%s", 
                category, datePath, UUID.randomUUID().toString().replace("-", ""), ext);

        try (InputStream stream = file.getInputStream()) {
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(serverProps.getDefaultBucket())
                    .object(key)
                    .stream(stream, file.getSize(), 10 * 1024 * 1024)
                    .contentType(file.getContentType())
                    .build());
        } catch (Exception e) {
            throw new RuntimeException("上传失败", e);
        }
        return serverProps.getEndpoint() + "/" + serverProps.getDefaultBucket() + "/" + key;
    }

    @Override
    public void fetchToResponse(String objectKey, HttpServletResponse resp) {
        try (InputStream stream = minioClient.getObject(GetObjectArgs.builder()
                .bucket(serverProps.getDefaultBucket())
                .object(objectKey)
                .build())) {
            
            StatObjectResponse stat = minioClient.statObject(StatObjectArgs.builder()
                    .bucket(serverProps.getDefaultBucket())
                    .object(objectKey)
                    .build());
            
            resp.setContentType(stat.contentType());
            resp.setHeader("Content-Disposition", 
                    "attachment;filename=" + URLEncoder.encode(objectKey, StandardCharsets.UTF_8));
            StreamUtils.copy(stream, resp.getOutputStream());
        } catch (Exception e) {
            throw new RuntimeException("下载失败", e);
        }
    }

    @Override
    public void removeObject(String objectKey) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(serverProps.getDefaultBucket())
                    .object(objectKey)
                    .build());
        } catch (Exception e) {
            throw new RuntimeException("删除失败", e);
        }
    }
}

YAML配置示例

oss:
  minio:
    endpoint: http://192.168.1.100:9000
    access-key: admin
    secret-key: SecurePass123
    default-bucket: app-files
标签: minioDocker

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。