はじめに
こんにちは。ニフティの山田です。
AWSを利用するうえで、S3を使うことは多いと思います。静的ファイル配信のみならず、アプリケーションから参照されることも多いでしょう。このようなアプリケーションの動作確認やテストの上では、ローカル環境で動くS3エミュレータがあると便利です。
しかし、従来有力だった以下の2つはいずれも無償提供が実質終了してしまいました。
- MinIO: Web UI機能が削除され、バイナリ提供が終了したため、実質的にOSS版は終了
- localstack for AWS: 利用にはlocalstackアカウントの発行と認証が必要となり、CIでの実行には有償契約が必須
そこで今回はこの代替となるものを探してみました。
移行先
Dockerイメージでサーバを立てることができ、複数コンテナの連携や複雑な初期化が必要ないものを選択します。
| S3Mock | SeaweedFS | RustFS | |
|---|---|---|---|
| イメージ名 | abode/s3mock | chrislusf/seaweedfs | rustfs/rustfs |
| 言語 | Java | Go | Rust |
| GitHub Stars | 1,031 | 29,900 | 20,900 |
| Web GUI | × | ◯ | ◯ |
| path-style access | ◯ | ◯ | ◯ |
| virtual-hosted-style access | × | × | × |
| バケット基本操作 | ◯ | ◯ | ◯ |
| オブジェクト基本操作 | ◯ | ◯ | ◯ |
| ListObjectsV2 | ◯ | ◯ | ◯ |
| multipart upload | ◯ | ◯ | ◯ |
| タグ | ◯ | ◯ | ◯ |
| 署名付きURL | △(署名を無視) | ◯ | ◯ |
| sigv4auth | × | ◯ | ◯ |
| バケットポリシー | × | ◯ | ◯ |
| バージョニング | ◯ | ◯ | ◯ |
| ライフサイクルポリシー | × | △(TTL設定のみ) | ? |
| CORS | × | ◯ | ? |
表は公式ドキュメントを参照したものであり、すべての機能を検証したわけではない点にご留意ください。
S3Mock
文字通りテストなどで利用するS3のモック用途で作られたものです。Testcontainersでの利用も公式に想定されています。GitHubでAPIごとのサポート状況がリストアップされている点も親切です。
docker composeでの起動例は以下の通りです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
services: s3mock: image: adobe/s3mock:4.11.0 environment: - COM_ADOBE_TESTING_S3MOCK_STORE_RETAIN_FILES_ON_EXIT=true - COM_ADOBE_TESTING_S3MOCK_STORE_ROOT=data - COM_ADOBE_TESTING_S3MOCK_STORE_INITIAL_BUCKETS=my-bucket ports: - 9090:9090 volumes: - s3mock-data:/data volumes: s3mock-data |
テスト用だけあってデフォルトだと終了時にデータ消去が走ってしまいますが、環境変数で永続化が可能です。また自動作成するバケット名を環境変数で設定できる点が便利です。
Pros
- エラーレスポンスなど、S3の挙動再現には最も期待できる
Cons
- 署名など高度機能には対応していない
- Web GUIはない
SeaweedFS
分散ストレージOSSの一つです。FUSE、Hadoopなど多くのプロトコルに対応しており、S3互換APIも備えています。
分散システムだけあってMaster・Volume・Filerなど複数コンポーネントから構成されていますが、S3をシングルノードで起動するだけなら以下でできます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
services: seaweedfs: image: chrislusf/seaweedfs:4.09 ports: - 8333:8333 # S3 API - 8888:8888 # Filer UI - 9333:9333 # Master UI command: ["server", "-s3", "-dir=/data", "-ip=0.0.0.0"] volumes: - seaweedfs-data:/data volumes: seaweedfs-data: |
上記設定だと無認証でアクセス可能です。簡易的ですがUI(上記のFiler UI)も備わっています。
Pros
- S3の高度機能にもある程度対応している
- Web GUIがあるので確認はしやすい
Cons
- 分散システムであるため、構成要素は多い
- 不具合があった際のデバッグは難しい
- あくまでもS3互換であるため、エラーレスポンスなど細かいとことで違いが出る可能性がある
RustFS
同じく分散ストレージOSSです。…とはいえまだアルファ版でありシングルノードでしか動作しません。MinIOの代替を目指している模様です。
docker composeでの起動方法は以下の通りです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
services: seaweedfs: image: rustfs:rustfs:1.0.0-alpha.82 environment: - RUSTFS_ACCESS_KEY=rustfsadmin - RUSTFS_SECRET_KEY=rustfsadmin - RUSTFS_CONSOLE_ENABLE=true ports: - 9000:9000 # S3 API - 9001:9001 # Admin UI volumes: - rustfs-data:/data volumes: rustfs-data: |
アクセスキー・シークレットが必須となります。(デフォルトはrustfsadmin/rustfsadmin)
Web GUIへのアクセスにも必要です。
OpenTelemetryにも対応しているらしく、docker composeのサンプルが用意されています。
Pros
- Web GUIを持ち、SeaweedFSよりモダンなデザイン
Cons
- まだalpha版
- ドキュメントがあまり詳細でない
- 認証トークンをハードコードしてCVSS 9.8の脆弱性を出したことがある
結論
個人的には
- テスト(Testcontainer)用
- S3Mock
- docker compose用
- GUI不要なら: S3Mock
- GUI必要なら: SeaweedFS
で良いのではないかと思っています。localstackほどの機能網羅性はありませんが、単純なCRUDL用途であれば実用に耐えるでしょう。私の担当プロダクトでは規模の小さいものからS3Mock/SeaweedFSへの置き換えを行っています。
Tips: 初期化方法
ローカル実行時やテスト開始時など、バケット作成・初期データ投入を自動的に行いたいケースがあります。
locakstackでは特定ディレクトリにhookスクリプトを置いておくと自動実行される機能がありましたが、上記のいずれもその機能はありません。(S3Mockのみ、バケット作成は自動実行可能)
初期化したければ、別途初期化用のコンテナを用意することになります。
ex) SeaweedFSに対してバケット作成、初期データ投入
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
seaweedfs: image: chrislusf/seaweedfs:4.09 ports: - 8333:8333 # S3 API - 8888:8888 # Filer UI - 9333:9333 # Master UI command: ["server", "-s3", "-dir=/data", "-ip=0.0.0.0"] volumes: - seaweedfs-data:/data healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:8333"] interval: 5s timeout: 5s retries: 10 seaweedfs-init: image: amazon/aws-cli:2.33.15 depends_on: seaweedfs: condition: service_healthy environment: AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_DEFAULT_REGION: ap-northeast-1 volumes: - ./mock-contents/data:/data:ro entrypoint: /bin/sh command: - -c - | aws --endpoint-url http://seaweedfs:8333 s3 mb s3://seaweedfs || true aws --endpoint-url http://seaweedfs:8333 s3 sync /data/ s3://seaweedfs/ echo "Initialization complete" |
- 初期化処理を行うコンテナ(上記のaws-cliコンテナ)を用意し、そこで初期化処理を実行する
- 上記ではバケット作成とs3 syncで初期化している
- depends_onで起動順の制御が必要
- プロセスの起動完了後に実行される必要があるため、S3コンテナ側にヘルスチェックの設定が必須
その他の選択肢
分散ストレージ
- Ceph
- Garage
- Zenko
など、S3互換APIを持つストレージOSSは他にもありますが、分散化を前提としておりセットアップが複雑です。ローカル・テスト用で使うには不向きかもしれません。
プロキシ
APIだけを提供し、他のストレージバックエンド(Google Cloud Storageなど)に対するプロキシとして機能するものです。
ファイルシステムバックエンドがあるので単独でも使えそうではありますが未検証です。
AWS SDKモック
- moto (python)
- aws-sdk-client-mock (JavaScript)
ユニットテスト用途であれば昔ながらの方法に立ち戻り、S3互換サーバを立てるのではなく、AWS SDKをモック化することで対応可能です。SDKレスポンスの再現度という点では最も力が入っています。
ただしテスト時にしか使えないので、ローカルPC上で環境を再現する用途には不向きです。また、複数アプリケーションを起動してのテストにも対応できません。
インメモリモック
- gofakes3 (Go)
インメモリでS3互換サーバを立てるものです。SDKモックとは異なりますが、テスト用途であり、やはり環境再現などには使えません。
おわりに
今回は、ローカルS3エミュレータの代替となるサービスについて解説しました。
参考になれば幸いです。


