PLAY DEVELOPERS BLOG

HuluやTVerなどの日本最大級の動画配信を支える株式会社PLAYが運営するテックブログです。

HuluやTVerなどの日本最大級の動画配信を支える株式会社PLAYが運営するテックブログです。

MinIO を用いてローカル開発環境に S3 互換ストレージを構築する

24卒で新卒入社いたしました、OTTサービス技術部第2グループの比嘉です。

私が配属されて初めて行なった業務で使って便利だったMinIO*1というツールについてご紹介します。 MinIOはクラウドサービスとして提供されていますが、Dockerなどを用いてローカル環境として使用することもできます。 今回はRuby on Rails + MinIOをローカル環境で使う方法とS3を並行して使う際の環境ごとの向き先制御についてお話しします。

背景

まず、開発要件としてS3のCSVファイルを取得し、そのデータを使ってDBのデータを追加したり、編集するという要件がありました。 そのため、開発を行なって動作確認を行うにはS3のバケットがなければいけません。 じゃあ、バケット作ればいいじゃないかという話かもしれませんがS3は低コストであっても利用料はかかるし他にも問題を抱えていました。

問題点1:AWSに接続できない

前述しておりますが、私は新卒入社して配属後すぐの業務で開発をスタートしました。そのためAWSに関して知識不足でした。S3は使い方によってはお金もかかってくるので、 開発業務やAWSに慣れるまではS3にリクエストしない方針となり、最初のうちは実際のS3にアクセスせずに開発を進める必要がありました。

問題点2:バケット名決まってない

バケット名が決まってなかったので仮に作ったとしてもそのバケットが使えなくなる可能性があります。新しく作ればいいかもしれませんが少し煩わしい問題です

これらの問題を受けローカルのテストする環境として先輩からMinIOというツールがあるという提案を受けました。

MinIOとは

読み方はミンアイオーらしいです。S3互換のストレージを作ることができます。クラウドサービスとして提供されているのが主らしいですが配布されているDockerイメージ*2を使えばローカルで構築することも可能です。 私は今回、Dockerイメージを使ってローカルで構築しました。

LocalStackとの違い

類似サービスとしてLocalStackが挙げられると思います。LocalStackはローカル環境を起動するたびにバケット内のデータが消えてしまいます。データを永続化するためにはPro版を購入するか、起動時に自動でデータを登録するスクリプトを組む必要があります。その点、MinIOは立ち上げ直したとしてもデータが残り続けます。

使用環境

  • Mac (14.4.1)
  • Rancher Desktop (1.16.0)
  • Ruby on Rails (3.1 and 7.2.2)
  • MinIO (RELEASE.2024-11-07T00-52-20Z)

DEMO環境構築

1. Rails プロジェクトを作成

まず新規Railsアプリを作成します。

rails new minio_app
cd minio_app

2. Dockerfile の編集

ルートディレクトリに作成されたDockerfileの内容を下記のように変更してください。

Dockerfile

FROM ruby:3.1

RUN mkdir /app
WORKDIR /app

COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock

RUN bundle install

COPY . /app

CMD ["rails", "server", "-b", "0.0.0.0"]

3. compose.yaml の作成

ルートディレクトリにcompose.yamlを作成してください

compose.yaml

version: '3'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/app
    depends_on:
      - minio
    environment:
      RAILS_ENV: development
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin

  minio:
    image: minio/minio
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - minio_data:/data
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin
    command: server /data --console-address ":9001"

volumes:
  minio_data:

4. Gemfile の更新

Gemfile に aws-sdk-s3 gem を追加してください。

gem 'aws-sdk-s3', require: false

Gemfileを更新したら下記コマンドを実行してください

docker compose run web bundle install

5. アプリの起動

コマンドを実行してアプリを動かしてください

docker compose up -d

http://localhost:3000/に接続できたら成功です

6. バケットの作成&テストファイルアップロード

http://localhost:9001/browserに接続してバケットを作成します。 compose.yamlで設定したユーザ名とパスワードでログインしてください。 Administrator>Buckets>Create Bucketsからバケットを作成してください。

バケット作成後、User>Object Browser>[作成したbucket]>Uploadからテスト用のCSVをアップロードしてください

test.csv

"name","age"
"yamada",13
"tanaka",16
"yamashita",19

7. アクセスキーの作成

User>Access Keys>Create access keyからアクセスキーを作成してください。 後から必要になるのでアクセスキーとシークレットアクセスキーは記録しておいてください。

接続テスト

Railsコンソールを用いて、RailsからMinIOに接続できることを確認します。

rails c
minio-app(dev)> require 'aws-sdk-s3'
minio-app(dev)> require 'csv'

minio-app(dev)> bucket_name = 'techblog'
minio-app(dev)> object_key = 'test.csv'

minio-app(dev)> s3_client = Aws::S3::Client.new(
   endpoint: 'http://127.0.0.1:9000',
   access_key_id: '[記録したアクセスキー]',
   secret_access_key: '[記録したシークレットアクセスキー]',
   force_path_style: true,
   region: 'ap-northeast-1'
)

minio-app(dev)> response = s3_client.get_object(bucket: bucket_name, key: object_key)

minio-app(dev)> csv_content = response.body.read

CSVの内容が表示されたら成功です。 これでMinIO上に保存されているファイルをRailsから参照できることを確認できました。

環境ごとの向き先制御

Configやdotenvなどを定数管理・環境変数管理系のgemを用いて環境ごとにs3_clientの向き先を制御することが可能です。 これにより、本番環境と開発環境でS3の向き先を動的に変更できます。 Configを用いて管理する例をご紹介します。

Gemfile

gem "config"

config/settings/development.yml

aws:
  s3:
    access_key_id: '[記録したアクセスキー]'
    secret_access_key: '[記録したシークレットアクセスキー]'
    region: 'ap-northeast-1'
    endpoint: 'http://127.0.0.1:9000'
    force_path_style: true

lib/utils/s3_client.rb

require "aws-sdk-s3"

module Utils
  class S3Client
    # 初期化
    # @param [String] bucket バケット名
    def initialize(bucket,
                   access_key_id: Settings.aws.s3.access_key_id,
                   secret_access_key: Settings.aws.s3.secret_access_key,
                   region: Settings.aws.s3.region)
      @bucket = bucket
      @access_key_id = access_key_id
      @secret_access_key = secret_access_key
      @region = region

      # MinIOでテストする時の設定
      if Rails.env.development?
        @endpoint = Settings.aws.s3.endpoint
        @force_path_style = Settings.aws.s3.force_path_style
      end

      s3_client
    end

    def read_file_content(key)
      response = s3_client.get_object(bucket: @bucket, key: key)
      response.body.read
    end

    private

    # S3クライアント
    # @return [Aws::S3::Client] AWSクライアント
    def s3_client
      if Rails.env.development?
        @s3_client = Aws::S3::Client.new(access_key_id: @access_key_id,
                                        secret_access_key: @secret_access_key,
                                        region: @region,
                                        endpoint: @endpoint,
                                        force_path_style: @force_path_style)
      else
        @s3_client = Aws::S3::Client.new(access_key_id: @access_key_id,
                                        secret_access_key: @secret_access_key,
                                        region: @region)
      end

      @s3_client
    end
  end
end

呼び出し

s3_client = Utils::S3Client.new(bucket_name)
respose = s3_client.read_file_content(object_key)

最後に

今回はMinIOを用いたローカルS3互換ストレージの構築方法について説明しました。 MinIOを用いることでネットワークに依存せず、S3を用いた開発の動作確認を行うことができます。 個人開発でも使いやすいと思うのでぜひ使ってみてください!

最後までご覧いただきありがとうございました。