近年、更新や書き換え頻度の少ない大容量データの保管、配信といった用途において、オブジェクトストレージの利用は当たり前となりました。オブジェクトストレージ上に置いたファイルを、CDN経由で配信するといった使い方も一般的です。
今回はセルフホストできるオープンソースのオブジェクトストレージであるSeaweedFSを紹介します。
SeaweedFSとは
クラウド上に構築された本番環境であれば、クラウドベンダーが提供するオブジェクトストレージを使うのが、対障害性やスケーラビリティ、コスト面からも最適でしょう。ですがオンプレミス環境や家庭内であれば、セルフホストできるオブジェクトストレージがほしくなります。またクラウドサービスは利用に費用がかかりますから、開発環境向けには無料で使えるスタブとして、APIに互換性のある代替プロダクトがあると便利です。
S3とAPI互換性のあるオブジェクトストレージとして、長らく人気だったのがMinIOです。本連載でも第655回で紹介しています。
MinIOはDockerコンテナをひとつ起動するだけで動かせる、非常にシンプルなオブジェクトストレージです。Webブラウザからオブジェクトを操作できるインターフェイスも同梱されており、開発用途では非常に便利でした。ところが2025年10月頃、MinIOはプロジェクトの方針を転換し、バイナリのリリースを停止しました。Dockerイメージの配布も行われなくなってしまったため、セキュリティアップデートに追従するためには、ユーザーは各自でソースコードをチェックアウトし、イメージをビルドしなくてはなりません。そのためMinIOは、もはや手軽に使えるとは言いづらくなってしまいました。
そんなMinIOからの移行先としては、RustFSやGarageなど、いくつかのプロダクトが注目されています。今回紹介するSeaweedFSも、そんな中のひとつです。
SeaweedFSは、シンプルでスケーラビリティの高い分散ファイルシステムです。もともとはFacebookのHaystack論文を実装することから始まったプロダクトです。実際のファイルを管理するボリュームサーバーと、そのボリュームサーバーを管理するマスターサーバーに分離した構成が特徴で、これによって高い高速性を実現していると謳っています。
SeaweedFSの構成
SeaweedFSは、機能ごとに分かれた設計となっています。
| 機能 | 用途 | 必須か |
|---|---|---|
| master | クラスタ全体の管理。クライアントに対するボリュームサーバーの割り当てなど。 | 必須 |
| volume | 実際のデータの格納先。 | 必須 |
| filer | オブジェクトストレージ上に、従来のファイルシステム同等のアクセスを提供。 | 推奨(実質必須) |
| s3/ |
S3互換APIやWevDAVといったアクセス手段を提供。 | オプション |
基本的にmasterとvolumeさえあれば、オブジェクトストレージとして動作します。しかしfilerなしでの運用は非現実的でしょう
Composeの設定と起動
今回は必須のmaster、volumeにくわえ、filerと、S3互換APIでのアクセスを可能にするs3を動かします。Docker Composeを使って一気に起動してしまいましょう。以下のcompose.
見ての通り、コンテナイメージはすべて同一のものを利用します。というのもSeaweedFSの機能はweedという単一のコマンドとして実装されており、サブコマンドによって使い分けるようになっているためです。これはコンテナのエントリーポイントに指定されているシェルスクリプトに、commandで指定したパラメータを渡すことで実現されています。
services:
master:
image: chrislusf/seaweedfs:4.03
ports:
- 9333:9333
- 19333:19333
command: 'master -ip=master -ip.bind=0.0.0.0'
volumes:
- master_data:/data
volume:
image: chrislusf/seaweedfs:4.03
ports:
- 8080:8080
- 18080:18080
command: 'volume -ip=volume -master="master:9333" -ip.bind=0.0.0.0 -port=8080'
volumes:
- volume_data:/data
depends_on:
- master
filer:
image: chrislusf/seaweedfs:4.03
ports:
- 8888:8888
- 18888:18888
command: 'filer -ip=filer -master="master:9333" -ip.bind=0.0.0.0'
volumes:
- filer_data:/data
tty: true
stdin_open: true
depends_on:
- master
- volume
s3:
image: chrislusf/seaweedfs:4.03
ports:
- 8333:8333
command: 's3 -filer="filer:8888" -ip.bind=0.0.0.0'
depends_on:
- master
- volume
- filer
volumes:
master_data:
volume_data:
filer_data:
以下のコマンドでコンテナ一式を起動します。
$ sudo docker compose up -d
API経由でSeaweedFSにアクセスしてみる
手始めに、SeaweedFSのAPIを使ったアクセスを体験してみましょう。まずmasterコンテナに対し、新しいファイルをアップロードするため、IDの割り当てを要求します。masterコンテナは9333番ポートでAPIを公開しています。
$ curl http://localhost:9333/dir/assign
{"fid":"3,0265da323b","url":"volume:8080","publicUrl":"volume:8080","count":1}
レスポンスJSON内のfid
続いてhello.
$ echo hello > hello.txt
$ curl -F file=@$(pwd)/hello.txt http://localhost:8080/3,0265da323b
{"name":"hello.txt","size":6,"eTag":"353dd8be","mime":"text/plain"}
アップロードした先のURLに対してGETしてみましょう。
$ curl http://localhost:8080/3,0265da323b hello
アップロードしたhello.
S3互換APIでSeaweedFSにアクセスする
前節の解説でわかるように、SeaweedFSのAPIを直接利用する場合、ファイル名ではなくfidを使う必要があります。これは人間にとって、お世辞にも直感的ではありません。というわけでオブジェクトストレージのデファクトスタンダードである、Amazon S3互換APIを使いましょう。ここでは定番のAWS CLIを例に解説します。インストールにはSnapを使うのが手軽です。
$ sudo snap install aws-cli --classic
AWSでは、アクセスキーとシークレットを使って認証します。ですがSeaweedFSはデフォルトで認証が設定されていません。とはいえ認証情報が空のままでは、awsコマンドが動かないため、アクセスキーとシークレットに適当な文字列を設定してください。ここでは環境変数AWS_
$ export AWS_ACCESS_KEY_ID="TEST_KEY" $ export AWS_SECRET_ACCESS_KEY="TEST_SECRET"
awsコマンドは、--endpoint-urlオプションでAPIのエンドポイントを指定できます。ここにs3コンテナが公開している8333番ポートを指定してください。これでs3サブコマンドがそのまま動作します。例えば以下は、my-bucketというバケットを作成する例です。
$ aws --endpoint-url http://localhost:8333 s3 mb s3://my-bucket make_bucket: my-bucket
先ほど作成したhello.
$ aws --endpoint-url http://localhost:8333 s3 cp hello.txt s3://my-bucket/ upload: ./hello.txt to s3://my-bucket/hello.txt
s3 lsコマンドで、ファイルが存在することを確認してみましょう。
$ aws --endpoint-url http://localhost:8333 s3 ls s3://my-bucket/ 2025-12-17 01:10:10 6 hello.txt
FUSEでUbuntuにマウントする
awsコマンドによるオブジェクトの操作は、慣れないとやりづらいかもしれません。SeaweedFSは、FUSEを使ってディレクトリツリーに直接マウントできます。ここではホストマシンに[1]ファイルシステムとしてマウントしてみましょう。
マウントにもweedコマンドを使うため、以下のコマンドでホストにインストールしてください。
$ wget https://github.com/seaweedfs/seaweedfs/releases/download/4.03/linux_amd64.tar.gz $ tar xf linux_amd64.tar.gz $ sudo cp weed /usr/local/bin
/mnt/
$ sudo mkdir /mnt/weed $ sudo weed mount -dir=/mnt/weed -filer=localhost:8888 -volumeServerAccess filerProxy -map.uid=$(id -u):0 -map.gid=$(id -g):0
ポイントは2つです。
マウントしたディレクトリにファイルを書き込もうとした際、クライアントはvolumeServerAccessに指定された方法で、volumeサーバーと通信します。デフォルト値はdirectで、この場合クライアントは、masterから通知されたvolumeサーバーのIPアドレスに直接アクセスしようとします。ところが今回の例では、volumeサーバーとmasterサーバーがDockerのコンテナネットワーク内で通信している都合上、
S3クライアントを使ってファイルをアップロードすると、filer上でそのファイルのオーナーはrootになります。そのためそのままマウントすると、ファイルに権限がなく、読み書きができません。
weed mountは、デフォルトではフォアグラウンドで動作します。マウントが完了したら別のターミナルを立ち上げて、/mnt/
$ ls /mnt/weed/ buckets $ ls /mnt/weed/buckets/ my-bucket $ ls -l /mnt/weed/buckets/my-bucket/ total 1 -rw-rw---- 1 mizuno mizuno 6 Dec 17 01:10 hello.txt
bucketsディレクトリの中に、先ほど作成したバケット名のディレクトリがあります。そしてその中に、アップロードしたhello.
$ cat /mnt/weed/buckets/my-bucket/hello.txt hello
今回は、MinIOに代わるセルフホスト可能なオブジェクトストレージの選択肢として、SeaweedFSを紹介しました。
SeaweedFSはMaster、Volume、Filerのように役割が明確に分かれているため、将来的にデータ量が増大した際にも、柔軟にスケールアウトできるという強みを持っています。S3互換APIが使用できるため、NextcloudのようなWebアプリケーションのバックエンドとして利用しても便利です。さらにFUSEマウントによって、Ubuntu上の通常のディレクトリとして扱える点は、既存のアプリケーションやスクリプトをそのまま流用したい場合に大きなアドバンテージとなるでしょう。MinIOと比較するとやや複雑な構成となっていますが、動かすだけであれば、見ての通りComposeで一発です。
ローカル環境でセルフホストできるオブジェクトストレージをお探しの場合は、SeaweedFSを試してみてください。