Nest.JS | Providers -> Min.io

MinIO is an open-source object storage server that is compatible with Amazon S3 API. It is designed to be scalable and high-performance, allowing you to store and retrieve large amounts of data quickly and easily. MinIO can be used as a standalone storage solution, or as a layer on top of other storage solutions to provide faster and more efficient data access.

MinIO is particularly useful in applications that need to store and retrieve large amounts of unstructured data, such as images, videos, and other media files. It can also be used in data processing applications that need to access large datasets, such as machine learning or big data analytics applications.

One of the advantages of using MinIO is its compatibility with Amazon S3 API. This makes it easy to integrate with existing applications and tools that use S3 API, and allows you to take advantage of the many S3-compatible tools and services available in the market. MinIO also offers features such as versioning, server-side encryption, and lifecycle management, making it a secure and reliable storage solution.

Installation

  1. Install Docker on your machine if it's not already installed. You can download it from the official Docker website: https://www.docker.com/get-started

2. Start the container

mkdir -p ${HOME}/minio/data

docker run \
   -p 9000:9000 \
   -p 9090:9090 \
   --user $(id -u):$(id -g) \
   --name minio1 \
   -e "MINIO_ROOT_USER=ROOTUSER" \
   -e "MINIO_ROOT_PASSWORD=CHANGEME123" \
   -v ${HOME}/minio/data:/data \
   quay.io/minio/minio server /data --console-address ":9090"

The example above works this way:

  • mkdir creates a new local directory at ~/minio/data in your home directory.
  • docker run starts the MinIO container.
  • -p binds a local port to a container port.
  • -user sets the username for the container to the policies for the current user and user group.
  • -name creates a name for the container.
  • -v sets a file path as a persistent volume location for the container to use. When MinIO writes data to /data, that data actually writes to the local path ~/minio/data where it can persist between container restarts. You can replace ${HOME}/minio/data with another location in the user’s home directory to which the user has read, write, and delete access.
  • -e sets the environment variables MINIO_ROOT_USER and MINIO_ROOT_PASSWORD, respectively. These set the root user credentials. Change the example values to use for your container.

3. Verify that the MinIO container is running by opening a web browser and navigating to http://localhost:9000. You should see the MinIO web interface.


Usage

Here's an example of how to create a Nest.js S3 client provider with MinIO:


1. Install the minio package using npm:

npm install --save @aws-sdk/client-s3

2. Create a new S3 config

import { registerAs } from '@nestjs/config';

export default registerAs('s3', () => ({
  accessKeyId: process.env.S3_ACCESS_KEY_ID
  secretAccessKey: process.env.S3_SECRET_ACCESS_KEY
  endpoint: process.env.S3_ENDPOINT
  region: process.env.S3_REGION || 'us-east-1'
}));

3. Create a new Nest.js provider class called S3Service:

import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';

interface UploadParams {
  bucket: string;
  name: string;
  body: Buffer;
}

@Injectable()
export default class S3Service {
  client!: S3Client;

  config;

  private logger = new Logger(S3Service.name);

  constructor(private configService: ConfigService) {
    this.config = this.configService.get('s3');

    if (!this.config.accessKeyId) {
      this.logger.warn(`S3 accessKeyId not found: ${JSON.stringify(this.config)}`);
      throw new Error('S3 access key ID not found');
    }

    this.client = new S3Client({
      endpoint: this.config.endpoint,
      credentials: {
        accessKeyId: this.config.accessKeyId,
        secretAccessKey: this.config.secretAccessKey,
      },
      region: this.config.region,
      forcePathStyle: true,
    });
  }

  upload({ bucket, name, body }: UploadParams) {
    const params = {
      Bucket: bucket,
      Key: name,
      Body: body,
    };

    return this.client.send(new PutObjectCommand(params));
  }
}

4. To use the MinioProvider class in other Nest.js classes, we need to add it to the module's providers array:

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import S3Service from './s3.service';

@Module({
  imports: [ConfigModule],
  providers: [S3Service],
  exports: [S3Service],
})
export default class S3Module {}

5. We can now inject the S3Service class into any other Nest.js class that requires access to the MinIO client. For example, here's how we can use it in a controller class:

import { Controller, Get } from '@nestjs/common';
import { S3Service } from './s3.service';

@Controller()
export class AppController {
  constructor(private s3Service: S3Service) {}

  @Get()
  async getHello(): Promise<string> {
  ...
     await this.s3Service.upload({
      bucket: BUCKET_NAME,
      name: FILE_NAME,
      body: file.buffer,
    });
    ...
  }
}