Rails開発でS3へのファイルアップロードやファイルダウンロードする機能を実装する際に MinIO なるものの話をよく聞くので実際に導入から使用するところまでやってみました。
そもそも MinIO って何なの?
ってことで公式サイトがあったので見てみました。
以下のリンクを見るとS3互換ストレージなるものを提供してもらえるようです。
参考: MinIO | AWS S3 Compatible Object Storage
ローカル開発環境向けに各人でAWSのS3バケットを用意してRailsアプリの環境設定変更したりする作業が不要になってRailsのファイルアップロードやファイルダウンロード等の動作確認が楽になりそうです!
MinIOのdockerイメージを使って構築していきます。
Dockerコンテナで使用したい人向けの起動方法を解説してるページもありどのようにDockerコンテナを起動して使用するかなども分かるようになっています。
その他にも mc(MinIO Client)があり独自の機能も充実しています!(起動時のバケット準備もこの機能を利用しています)
Exabyte scale infrastructure requires specific features that extend beyond the core #objectstore. That’s why we’re introducing the MinIO Enterprise Object Store.
Designed for commercial customers, the #EnterpriseObjectStore includes features that span observability, key… pic.twitter.com/VGQUVoePzV
— MinIO (@Minio) March 12, 2024
事前準備
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
追加した機能を使用してファイルのアップロード、及びファイルのダウンロードが行えることを確認してみます。
http://localhost:3001/photos
にアクセスします。-
新規登録をクリックして、登録画面に遷移します。
-
Title
Describe
Image
を入力して、Create Photo
をクリックして、Photoを登録します。
-
詳細画面に遷移し、登録した内容(
Title
Describe
Image
)が表示されます。アップロードした画像も表示されていていい感じです!
MinIO
先ほどアップロードしたファイルがブラウザ経由のMinIOからも参照できるか確認してみます。
localhost:9001
にアクセスしてログインします。-
サイドメニューの
Object Browser
を選択すると存在するバケットが表示されるのでrails-photo-minio
をクリックします。
-
アップロードしたファイルが一覧に表示されてるので良さそうです!
-
ファイルを選択するとメニューが出てくるので Preview でアップロードしたファイルか確認することができます!
MinIOを使ってみての感想
Docker起動時にMinIOのバケットを作ったりと環境構築を自動化できたりするので初期設定さえしてしまえば開発環境を共有しやすいように感じました。
ブラウザからMinIOを使用してみた感じも直観的に操作をできるので使いやすいプロダクトだなぁなんて思いました。
気になった方はぜひ使用してみてください。
最後に
以下の記事を参考にcompose.ymlへの追加やRailsアプリの追加を行いました。ありがとうございました!
参考: 【MinIO】RailsアプリケーションにS3互換ストレージ MinIO を導入してみる
参考: Docker と MinIO を使った ActiveStorage 開発環境の構築