はじめに
adobe/s3mock
を使うことでAWS S3をモック化することができます。
ローカル開発環境のDockerにadobe/s3mock
を追加することで、実際のAWS S3を利用せずともS3の機能を実現することができます。
導入方法
adobe/s3mockの追加
docker-compose.yml
に下記を追加することでadobe/s3mock
を利用することができます。
services:
web:
...
+ s3:
+ image: adobe/s3mock
+ environment:
+ - initialBuckets=my-bucket
+ - retainFilesOnExit=true
+ - root=/s3mock
+ ports:
+ - "9090:9090"
+ volumes:
+ - s3_data:/s3mock
volumes:
+ s3_data:
...
environment
にinitialBuckets
を指定することで、最初からバケットを作成しておくことができます。
retainFilesOnExit
をtrue
に指定し、root
で指定したパスをvolume化することで、
投稿した画像を永続化することができます。
aws-sdk-s3を使用した画像投稿
adobe/s3mock
を導入できたので、早速aws-sdk-s3
を使用して画像を投稿したいと思います。
まずGemfile
にaws-sdk-s3
を追加します。
gem 'aws-sdk-s3', '~> 1'
config/initializers/aws.rb
などのファイルを作成して、region
, credentials
を設定します。
ローカル環境でadobe/s3mock
を使用する場合は、endpoint
を'http://s3:9090'
(s3
はdocker-compose.yml
に記載したサービス名)、force_path_style
をtrue
に指定します。
AWS上のS3に実際アクセスはしないので、ENV["AWS_ACCESS_KEY"]
とENV["AWS_SECRET_ACCESS_KEY"]
は適当な値で大丈夫です。
Aws.config.update({
region: 'ap-northeast-1',
credentials: Aws::Credentials.new(ENV["AWS_ACCESS_KEY"], ENV["AWS_SECRET_ACCESS_KEY"])
})
if Rails.env.development?
Aws.config.update({
endpoint: 'http://s3:9090',
force_path_style: true
})
end
動作確認
initialBuckets
にmy-bucket
を指定しているので、デフォルトでmy-bucket
のバケットが作成されていることが確認できます。
s3 = Aws::S3::Resource.new
s3.buckets.each {|b| p b.name }
=> "my-bucket"
画像をアップロードすることもできます。
file_path = Rails.root.join('sample.jpg')
obj = s3.bucket('my-bucket').object('image/sample.jpg')
obj.upload_file(file_path)
署名付URLを発行しアップロードした画像を表示することもできます。
ただし、endpoint
にhttp://s3:9090
を指定しているため、デフォルトでは
http://s3:9090/my-bucket/image/sample.jpg?
から始まるURLが発行され
そのままではブラウザから画像を表示することができません。
なので、画像を表示する際にはendpoint
を'http://localhost:9090'
に指定するといいと思います。
client = Aws::S3::Client.new(endpoint: 'http://localhost:9090')
signer = Aws::S3::Presigner.new(client: client)
@url = signer.presigned_url(:get_object, bucket: 'my-bucket', key: 'image/sample.jpg')
=> "http://localhost:9090/my-bucket/image/sample.jpg?から始まるURL"
生成した@url
はimage_tag
で実際に表示することができます。
<%= image_tag @url %>
CarrierWaveを使用した画像投稿
Gemfile
にcarrierwave
とfog-aws
を追加します。
gem 'carrierwave'
gem 'fog-aws'
ローカル環境でadobe/s3mock
を使用する場合は、endpoint
を'http://s3:9090'
、force_path_style
をtrue
に指定します。
ブラウザから画像を表示することができるよう
config.asset_host
には'http://localhost:9090/my-bucket'
を指定します。
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'
CarrierWave.configure do |config|
if Rails.env.development?
config.storage :fog
config.fog_provider = 'fog/aws'
config.fog_directory = 'my-bucket'
config.fog_credentials = {
provider: 'AWS',
aws_access_key_id: ENV['AWS_ACCESS_KEY'],
aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
region: 'ap-northeast-1',
endpoint: 'http://s3:9090',
path_style: true
}
config.asset_host = 'http://localhost:9090/my-bucket'
end
end
後は、画像を投稿したいモデルに「アップロード画像用のカラム」と「アップローダークラス」を用意し、
アップローダークラスのstorage
を:fog
にすることでadobe/s3mock
を使用した画像投稿が行えます。
storage :fog
ActiveStorageを使用した画像投稿
S3を利用するActiveStorageの設定にすれば大丈夫です。
'aws-sdk-s3'
を利用するので、endpoint
などの設定はconfig/initializers/aws.rb
でしているので追加で設定を行う必要はありません。
config.active_storage.service = :amazon
amazon:
service: S3
access_key_id: <%= ENV["AWS_ACCESS_KEY"] %>
secret_access_key: <%= ENV["AWS_SECRET_ACCESS_KEY"] %>
region: ap-northeast-1
bucket: my-bucket
注意点
ActiveStorageを使用する場合、endpoint
が'http://s3:9090'
のままなので
このままだとブラウザから画像を表示することができません。
なので、ブラウザで画像も表示したい場合はさらにもう一工夫してあげる必要がありそうです。