結構苦戦したので忘備録として書いとく。
LocalStackとは
この辺よんでください。
https://github.com/localstack/localstack
https://qiita.com/rio_matsui/items/e0c2c772d4579d00a312
LocalStackの設定
とりあえずdocker-compose.ymlには下記のように書く
localstack:
image: localstack/localstack:0.12.1
environment:
SERVICES: s3
AWS_ACCESS_KEY: 1234
AWS_SECRET_ACCESS_KEY: 12345678
DEFAULT_REGION: ap-northeast-1
DATA_DIR: /data
START_WEB: 0
HOSTNAME_EXTERNAL: localstack
INIT_SCRIPTS_PATH: /root/init
volumes:
- localstack-data:/data
- ./docker/localstack:/root/init
ports:
- 4566:4566
volumes:
localstack-data:
driver: local
以下説明
環境変数
SERVICES: s3
ここには使いたいサービスを記述する、複数使いたい場合はカンマ区切りで書く。
AWS_ACCESS_KEY: 1234
AWS_SECRET_ACCESS_KEY: 12345678
ここは適当でいい、SECRETは8文字以上じゃないと怒られる
DEFAULT_REGION: ap-northeast-1
ここもとりあえずお好みで。
DATA_DIR: /data
永続化させるデータの保存場所、Volumeを作成してこのディレクトリにマウントさせている。
START_WEB: 0
LocalStackには管理画面みたいなものが一応あるが、
使いたい場合はlocalstack/localstack-fullというイメージを使う必要がある。
localstack/localstackだと管理画面は使えないのだがログをみると起動しようとしてエラーを吐いているので無効にする。
HOSTNAME_EXTERNAL: localstack
理由はたぶんここに書かれているのと一緒。
これを書かないとRails側のコンテナからアクセスができない。
https://qiita.com/imunew/items/b74cecb7e12a9b9c4441
INIT_SCRIPTS_PATH: /root/init
初期化用のスクリプトの配置場所
ここに下記のようなのスクリプトを書いて置いておくと起動時に実行してくれる。
cd /root/init
# コンテナにはawslocalが入ってるのでそちらを使ってBucketを作成する
awslocal s3 mb s3://test-bucket
今回は作成したスクリプトをコンテナ側にマウントして実行するようにしている。
- ./docker/localstack:/root/init
ここに書いてない環境変数はここを参照
https://github.com/localstack/localstack#configurations
Port
ports:
- 4566:4566
LocalStackでは4566でアクセスを受け付けているのでポートフォワーディングを設定いれておく
ちなみにawscliで叩く場合は下記のようにEndpointを指定する。
aws --endpoint=http://localhost:4566 s3 ls s3://test-bucket --recursive
コンテナ内からの場合はawslocalコマンドが入ってるのでそちらを使うほうが楽。
これで立ち上げるとS3にBucketが作成されているはず。
aws --endpoint=http://localhost:4566 s3 ls
2020-11-02 10:12:10 test-bucket
Rails側の設定
ActiveStorageでS3を使うための設定はこのあたりのページを参照。
https://qiita.com/tsubasan1122/items/0171fe04754a760f7e4a
ここではLocalStackを使うのに必要な設定だけを記載
storage.yml
localstack:
service: S3
access_key_id: 1234
secret_access_key: 12345678
region: ap-northeast-1
endpoint: http://localstack:4566
force_path_style: true
bucket: test-bucket
以下説明
service: S3
access_key_id: 1234
secret_access_key: 12345678
region: ap-northeast-1
ここはLocalStack側の設定に合わせておく
endpoint: http://localstack:4566
force_path_style: true
awsのapiの叩き先をlocalstack側に変更するために設定する。
ただし、このままだとS3にアクセスする際にhttp://#{endpoint}.#{Bucket名}でアクセスしにいこうとするため
force_path_styleというオプションをtrueにして回避する。
これで、LocalStack側に保存されるようになったはず。
以下確認
# 適当に画像を保存
file = "1.jpg"
content_type = 'image/jpg'
image = Image.first
image.image.attach(io: File.open(file), filename: File.basename(file), content_type: content_type)
# S3の画像のキーを確認
image.image.attachment.blob.key
"p1fp3sd0mqxscrvcx960nqa7caal"
# localstack側に画像が保存されているか確認
aws --endpoint=http://localhost:4566 s3 ls s3://test-bucket
2020-11-02 11:59:17 14845 p1fp3sd0mqxscrvcx960nqa7caal # 同一のキーが存在する
その他
ファイルの保存はできるが、画像をブラウザに表示させようとしたときに取得されるURLのドメインが http://localstack:4566 になってしまう。
この辺は下記のページのようにURLを返すメソッドを作成して対応した。
https://qiita.com/shouta-dev/items/0b9569bf5522cca4cf3c