在 Ubuntu 上搭建 MinIO 服务器

在日常开发时,如果有文件上传下载的需求(比如用户头像),但是又不想使用对象存储,那么自己搭建一个 MinIO 服务器是一个比较简单的解决方案。

MinIO 是一个基于 Apache License v2.0 开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从 几kb 到最大 5T 不等。

MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。


MinIO 中文网站:https://www.minio.org.cn/docs/minio/linux/operations/installation.html

部署 MinIO 并修改 minioadmin 的账户密码

本文主要介绍在 Ububtu 上单节点单硬盘部署 MinIO,步骤如下:

下载 MinIO 服务器

shell 复制代码
wget https://dl.min.io/server/minio/release/linux-amd64/minio

为 MinIO 二进制文件添加执行权限

shell 复制代码
chmod +x minio

在合适的位置创建一个文件夹,用于存储 MinIO 上传的文件数据

shell 复制代码
# 在根目录创建 minio-data 文件夹,存储 MinIO 上传的文件数据
mkdir ~/minio-data

安装 MinIO。将 MinIO 的二进制文件移到 /usr/local/bin/目录下,以使其全局可用

shell 复制代码
sudo mv minio /usr/local/bin/

使用持久化环境变量作为 MinIO console 的登录账户和密码。

编辑 .bashrc文件,这里使用 nano。

shell 复制代码
nano ~/.bashrc

在文件的最后加上环境变量

shell 复制代码
export MINIO_ROOT_USER=newrootuser
export MINIO_ROOT_PASSWORD=newrootpassword

重新加载.bashrc以使更改生效

shell 复制代码
source ~/.bashrc

启动 MinIO

shell 复制代码
nohup minio server --secure ~/minio-data

这里使用nohup确保会话关闭之后 MinIO 不会停止,也可以使用screen等会话技术,或者将 MinIO 作为一个服务启动。这里不做过多介绍。

启动 MinIO 之后,在浏览器访问 ip+9000 端口即可访问 MinIO 的 Web 控制台。如果访问不了,请先检查 MinIO 的两个端口是否已经开放,一个是 MinIO 的 WebUI 端口,这个是随机的;一个是 MinIO 的 API 端口,这个固定是 9000。

在浏览器访问 ip+9000 实际会跳转到 WebUI 的端口。但是在使用 API 上传下载文件需要使用 9000 端口。


给 MinIO 配置域名

如果不想直接暴露 MinIO 的地址和端口,则可以使用 Nginx 给 MinIO 配置域名访问。

在此之前,您需要先准备一个已备案的域名并解析到当前服务器。

步骤如下:

先安装 Nginx (如果没有的话)

shell 复制代码
sudo apt-get update
sudo apt-get install nginx

一般不建议直接更改位于/etc/nginx/nginx.conf的 nginx 主配置文件。采用如下的配置方式:

/etc/nginx/sites-available/创建新的配置文件,可以直接以当前配置的域名未文件名。我这里由于需要配置多个域名,文件名叫做minio.conf

shell 复制代码
cd /etc/nginx/sites-available/
touch minio.conf

书写配置文件

shell 复制代码
nano minio.conf

配置文件示例

xml 复制代码
# WebUI 配置
server {
    listen 80;
    server_name yourdomain.com; # 替换为您的域名

    location / {
        proxy_pass http://localhost:44366;  # 替换为实际的端口
        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;
    }
}

# API 配置
server {
    listen 80;
    server_name api.yourdomain.com; # 替换为您的API域名

    location / {
        proxy_pass http://localhost:9000;   # 替换为实际的端口
        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;
    }
}

启用新创建的配置文件。将/etc/nginx/sites-available/minio.conf链接到/etc/nginx/sites-enabled/目录

shell 复制代码
sudo ln -s /etc/nginx/sites-available/minio.conf /etc/nginx/sites-enabled/

可以先检查一下 nginx,确认没有语法错误

shell 复制代码
nginx -t

重启 nginx 服务

shell 复制代码
sudo systemctl restart nginx

此时,在本机浏览器上应该可以用域名访问 Minio console 了。


MinIO 调用示例

在 SpringBoot 中调用

先添加依赖

xml 复制代码
<dependencies>
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.4.3</version>
    </dependency>
</dependencies>

然后创建一个服务类来实现文件的上传下载

java 复制代码
import io.minio.*;
import io.minio.messages.Item;

import java.io.InputStream;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.UUID;

@Service
public class MinIOService {

    private final MinioClient minioClient;

    public MinIOService() {
        try {
            // 配置更改成自己的,建议写在配置文件中
            this.minioClient = MinioClient.builder()
                    .endpoint("http://localhost:9000")
                    .credentials("minioadmin", "minioadmin")
                    .build();
        } catch (MinioException e) {
            throw new RuntimeException("Failed to create MinioClient", e);
        }
    }

    public String uploadFile(String bucketName, String objectName, InputStream stream, long size) {
        try {
            minioClient.putObject(bucketName, objectName, stream, size);
            return "File uploaded successfully.";
        } catch (MinioException | IOException e) {
            throw new RuntimeException("File upload failed.", e);
        }
    }

    public InputStream downloadFile(String bucketName, String objectName) {
        try {
            return minioClient.getObject(bucketName, objectName);
        } catch (MinioException | IOException e) {
            throw new RuntimeException("File download failed.", e);
        }
    }
}

并为其书写对应的 Controller

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

@RestController
@RequestMapping("/minio")
public class MinIOController {

    @Autowired
    private MinIOService minIOService;

    @PostMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file) {
        String bucketName = "my-bucket";
        String objectName = UUID.randomUUID().toString();
        try (InputStream stream = file.getInputStream()) {
            return minIOService.uploadFile(bucketName, objectName, stream, file.getSize());
        } catch (IOException e) {
            return "Failed to upload file.";
        }
    }

    @GetMapping("/download/{objectName}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String objectName) {
        String bucketName = "my-bucket";
        InputStream stream = minIOService.downloadFile(bucketName, objectName);
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + objectName + "\"")
                .body(new InputStreamResource(stream));
    }
}

在 Flask 中调用

下载依赖

shell 复制代码
pip install minio

然后创建一个 Flask 来集成 MinIO

python 复制代码
from flask import Flask, request, send_file, jsonify
from minio import Minio
from minio.error import S3Error

app = Flask(__name__)

# MinIO配置
minio_client = Minio(
    # 更改成自己的
    "localhost:9000",
    access_key="minioadmin",
    secret_key="minioadmin",
    secure=False
)

@app.route('/upload', methods=['POST'])
def upload_file():
    file = request.files['file']
    bucket_name = 'my-bucket'
    object_name = file.filename
    try:
        with open('/tmp/' + object_name, 'wb') as f:
            f.write(file.read())
        minio_client.fput_object(bucket_name, object_name, '/tmp/' + object_name)
        return jsonify({'message': 'File uploaded successfully'}), 200
    except S3Error as exc:
        return jsonify({'error': str(exc)}), 500

@app.route('/download/<object_name>', methods=['GET'])
def download_file(object_name):
    bucket_name = 'my-bucket'
    try:
        response = minio_client.get_object(bucket_name, object_name)
        return send_file(
            response.stream,
            as_attachment=True,
            attachment_filename=object_name,
            mimetype=response.headers['content-type']
        )
    except S3Error as exc:
        return jsonify({'error': str(exc)}), 500

if __name__ == '__main__':
    app.run(debug=True)

推荐阅读

MinIO Plus:https://mp.weixin.qq.com/s/kSkC3X-SQqo5GzXt-H66xw

相关推荐
杰哥技术分享9 分钟前
在 CentOS 上安装 Docker 和 Docker Compose 并配置使用国内镜像源
linux·docker·centos
知更鸟呆呆13 分钟前
【Linux操作系统】基础开发工具(yum、vim、gcc/g++)
linux·运维·vim
程序员岳焱13 分钟前
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
后端·sql·mysql
xiangyong5814 分钟前
ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
linux·ubuntu·gnu
龚思凯19 分钟前
Node.js 模块导入语法变革全解析
后端·node.js
天行健的回响22 分钟前
枚举在实际开发中的使用小Tips
后端
wuhunyu28 分钟前
基于 langchain4j 的简易 RAG
后端
techzhi28 分钟前
SeaweedFS S3 Spring Boot Starter
java·spring boot·后端
t198751281 小时前
Linux 上的 Tomcat 端口占用排查
linux·tomcat·firefox
写bug写bug2 小时前
手把手教你使用JConsole
java·后端·程序员