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を用いた開発の動作確認を行うことができます。 個人開発でも使いやすいと思うのでぜひ使ってみてください!
最後までご覧いただきありがとうございました。