Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

MinIOを導入して使ってみた話

Rails開発でS3へのファイルアップロードやファイルダウンロードする機能を実装する際に MinIO なるものの話をよく聞くので実際に導入から使用するところまでやってみました。

そもそも MinIO って何なの?

ってことで公式サイトがあったので見てみました。

以下のリンクを見るとS3互換ストレージなるものを提供してもらえるようです。

参考: MinIO | AWS S3 Compatible Object Storage

ローカル開発環境向けに各人でAWSのS3バケットを用意してRailsアプリの環境設定変更したりする作業が不要になってRailsのファイルアップロードやファイルダウンロード等の動作確認が楽になりそうです!

MinIOのdockerイメージを使って構築していきます。
Dockerコンテナで使用したい人向けの起動方法を解説してるページもありどのようにDockerコンテナを起動して使用するかなども分かるようになっています。
その他にも mc(MinIO Client)があり独自の機能も充実しています!(起動時のバケット準備もこの機能を利用しています)

事前準備

compose.ymlの編集からRailsアプリの設定までを行います。

MinIOの準備

  • 1. compose.yml に MinIO を追加します。

起動時にバケットrails-photo-minioがなければ作られるように設定しています!

services:
  web:
(省略)
+  minio:
+    image: minio/minio:latest
+    command: ["server", "/data", "--console-address", ":9001"]
+    ports:
+      - 9000:9000
+      - 9001:9001
+    volumes:
+      - minio:/data
+    environment:
+      MINIO_ROOT_USER: minio
+      MINIO_ROOT_PASSWORD: minio_password
+  createbuckets:
+    image: minio/mc
+    depends_on:
+      - minio
+    entrypoint: >
+      /bin/sh -c "
+      until (/usr/bin/mc config host add myminio http://minio:9000 minio minio_password) do echo '...waiting...' && sleep 1; done;
+      /usr/bin/mc mb myminio/rails-photo-minio;
+      /usr/bin/mc policy download myminio/rails-photo-minio;
+      exit 0;
+      "
volumes:
+  minio:
+    driver: local
  • 2. 起動して MinIO にアクセスしてみます。
    a. docker compose up -d --buildでビルドしつつコンテナを起動させます。
    b. ブラウザから localhost:9001 にアクセスして MinIO に接続できるようになっていると思います!

c. UsernameにenvironmentのMINIO_ROOT_USER、PasswordにenvironmentのMINIO_ROOT_PASSWORDを入力してログインします。
d. ログインして Object Browser の一覧にバケット(rails-photo-minio)が作られていれば成功です!

Railsアプリの設定

1. RailsからMinIOを参照できるように環境変数を設定します。

services:
  web:
    build: .
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3001 -b '0.0.0.0'"
    volumes:
      - .:/app
    ports:
      - 3001:3001
    depends_on:
      - db
    tty: true
    stdin_open: true
+    environment:
+      AWS_S3_BUCKET: rails-photo-minio
+      AWS_S3_ENDPOINT: http://minio:9000
+      AWS_ACCESS_KEY_ID: minio
+      AWS_SECRET_ACCESS_KEY: minio_password
+      AWS_S3_FORCE_PATH_STYLE: true
(省略)

(補足)
portsに3001を指定しています。
これはRailsのポート番号を変更する実験のために変更しており、MinIOのためにポート番号を変更する必要はありません。

2. storage.ymlのlocalをS3に変更します。

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
-  service: Disk
-  root: <%= Rails.root.join("storage") %>
+  service: S3
+  access_key_id: <%= ENV.fetch('AWS_ACCESS_KEY_ID', '') %>
+  secret_access_key: <%= ENV.fetch('AWS_SECRET_ACCESS_KEY', '') %>
+  region: "us-east-1"
+  endpoint: <%= ENV.fetch('AWS_S3_ENDPOINT', '') %>
+  bucket: <%= ENV.fetch('AWS_S3_BUCKET') %>
+  force_path_style: <%= ENV.fetch('AWS_S3_FORCE_PATH_STYLE', 'false') %>
+  public: false

3. Gemfileに"aws-sdk-s3"がなければ追加します。

(省略)
group :development, :test do
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
+  gem "aws-sdk-s3", require: false
end

4. docker compose up -d --buildでビルドしつつ起動させます。

機能追加

テーブル追加から実際に機能を使用できるところまで進めます。ファイルアップロードとアップロードしたファイルの参照ができるまでの最低限の機能実装を行います。

1. マイグレーションファイルを作成する。 bin/rails db:migrateを実行します。

class CreatePhotos < ActiveRecord::Migration[7.0]
  def change
    create_table :photos do |t|
      t.string :title
      t.text :describe

      t.timestamps
    end
  end
end

2. モデルを作成します。

class Photo < ApplicationRecord
  has_one_attached :image # 追加
end

3. コントローラを作成します。

class PhotosController < ApplicationController
  def index
    @photos = Photo.all
  end

  def show
    @photo = Photo.find(params[:id])
  end

  def new
    @photo = Photo.new
  end

  def create
    @photo = Photo.new(photo_params)

    if @photo.save
      redirect_to @photo
    else
      render :new
    end
  end

  private

  def photo_params
    params.require(:photo).permit(:title, :descibe, :image)
  end
end

4. ルーティングを追加します。

Rails.application.routes.draw do
  resources :photos
end

5. viewファイルを作成します。

  • index.html.erb
<h1>Photos</h1>
<%= link_to '新規登録', new_photo_path %>

<div>
  <ul>
    <% @photos.each do |photo| %>
      <li id="photo_<%= photo.id %>"><%= link_to photo.title, photo %></li>
    <% end %>
  </ul>
</div>
  • show.html.erb
<p><strong>Title:</strong><%= @photo.title %></p>
<p><strong>Describe:</strong><%= @photo.describe %></p>
<p>
  <% if @photo.image.attached? %>
    <%= image_tag @photo.image %>
  <% end %>
</p>
<%= link_to 'Back to Photos', photos_path %>
  • new.html.erb
<h1>New Photo</h1>

<%= form_with model: @photo, local: true do |form| %>
  <div>
    <%= form.label :title %><br>
    <%= form.text_field :title %>
  </div>

  <div>
    <%= form.label :describe %><br>
    <%= form.text_area :describe %><br>
  </div>

  <div>
    <%= form.label :image %><br>
    <%= form.file_field :image %>
  </div>

  <div><%= form.submit %></div>
<% end %>

<%= link_to 'Back to Photos', photos_path %>

動作確認

Railsアプリからファイルアップロードして MinIO に登録されるか見ていきます。

Rails

追加した機能を使用してファイルのアップロード、及びファイルのダウンロードが行えることを確認してみます。

  1. http://localhost:3001/photosにアクセスします。

  2. 新規登録をクリックして、登録画面に遷移します。

  3. Title Describe Imageを入力して、Create Photoをクリックして、Photoを登録します。

  4. 詳細画面に遷移し、登録した内容(Title Describe Image)が表示されます。アップロードした画像も表示されていていい感じです!

MinIO

先ほどアップロードしたファイルがブラウザ経由のMinIOからも参照できるか確認してみます。

  1. localhost:9001にアクセスしてログインします。

  2. サイドメニューのObject Browserを選択すると存在するバケットが表示されるのでrails-photo-minioをクリックします。

  3. アップロードしたファイルが一覧に表示されてるので良さそうです!

  4. ファイルを選択するとメニューが出てくるので Preview でアップロードしたファイルか確認することができます!

MinIOを使ってみての感想

Docker起動時にMinIOのバケットを作ったりと環境構築を自動化できたりするので初期設定さえしてしまえば開発環境を共有しやすいように感じました。
ブラウザからMinIOを使用してみた感じも直観的に操作をできるので使いやすいプロダクトだなぁなんて思いました。
気になった方はぜひ使用してみてください。

最後に

以下の記事を参考にcompose.ymlへの追加やRailsアプリの追加を行いました。ありがとうございました!

参考: 【MinIO】RailsアプリケーションにS3互換ストレージ MinIO を導入してみる
参考: Docker と MinIO を使った ActiveStorage 開発環境の構築


BPSアドベントカレンダー2024


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。