0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MinIOの公式イメージが消えた - 使うS3 APIを5つに絞って後継を実機比較し、フォークを固定して採用した

0
Posted at

TL;DR

  • ローカル開発と CI で S3 の代わりに使っていた MinIO の公式イメージ(Docker Hub の minio/minio と minio/mc)が、ある日 404 になりました
  • その日から、全 PR の統合テストが pull access denied で失敗しました。quay.io のイメージも匿名では pull できません
  • 後継を探す前に、バッチが S3 に求める機能を洗い出しました。使う API は 5 つだけで、あとは path-style のアクセスと、mc による初期化です
  • 8 つの選択肢を比べ、最後の 2 つ(MinIO のコミュニティフォークと RustFS)は実機で統合テストを流して比べました
  • 採用したのはフォークの pgsty/minio です。変更がイメージ名だけで済み、CI をすぐ戻せるからです。代わりに、タグとダイジェストの両方でイメージを固定し、配布が止まったときの切り替え先(RustFS)も先に決めました

この記事の対象読者

  • ローカル開発や CI で MinIO を S3 の代わりに使っている方
  • 使っていた OSS のイメージが突然消えて、後継を探している方
  • コミュニティのフォークに依存するときのリスクを、どう抑えるか考えている方

環境

  • Go(AWS SDK for Go v2)で書いたバッチ。本番は Amazon S3、ローカルと CI は S3 互換のストレージ
  • Docker Compose(ローカル開発用とテスト用の 2 つ)
  • GitHub Actions(PR ごとに統合テストを実行)
  • 比較したイメージ: pgsty/minio(RELEASE.2026-08-04T00-00-00Z)、rustfs/rustfs(1.0.0)

背景:ある日、全 PR の統合テストが落ちた

テナント単位でデータを整理するバッチを開発しています。このバッチは、本番では Amazon S3 を使います。ローカル開発と CI では AWS に接続せず、S3 互換の MinIO で代わりをさせていました。同じ S3 の API で、再現性のある検証をするためです。

ある日を境に、全 PR の統合テストが次のエラーで落ちるようになりました。

pull access denied for minio/minio, repository does not exist or may require 'docker login'

Docker Hub の minio/minio と minio/mc が、どちらも 404 になっていました。最後に統合テストが通ったのは 2026-09-09 で、2026-09-16 以降はすべて失敗していました。

別の配布先の quay.io にも同じ名前のイメージはありますが、匿名では pull できません(401)。同じイメージを使うローカル開発の環境も、新しく作れなくなっていました。

後継を探す前に、要件を絞った

最初にやったのは、代わりのイメージを探すことではありませんでした。バッチが S3 に何を求めているかを洗い出すことです。

MinIO は S3 の多くの API を実装しています。しかしバッチが使っているのは、そのごく一部でした。

要件 中身
使う S3 の API PutObject / ListObjectsV2 / DeleteObject / DeleteObjects / HeadBucket の 5 つ
アクセスの方式 path-style(SDK の設定で UsePathStyle = true)
起動時の初期化 バケットの作成と初期データの投入。MinIO のクライアント mc を使うスクリプトがある
ローカル開発で欲しいもの データの永続化と、中身を確かめられる GUI

要件が分かると、比べる観点がはっきりします。「MinIO と同じくらい高機能か」ではなく、「この 5 つの API と path-style と初期化が動くか」を見ればよいからです。

8 つの選択肢を比べた

選択肢 概要 評価
pgsty/minio + pgsty/mc MinIO のコミュニティフォーク(pgsty/silo、AGPL-3.0)が公開するイメージ 採用
RustFS Rust 製の S3 互換ストレージ(Apache-2.0)。1.0.0 の GA は 2026-09-16 代替候補の第一位
adobe/s3mock テスト用の S3 互換サーバー(Apache-2.0) CI には十分。ただし GUI が無く、再起動をまたいだデータの再利用は公式にはサポートされない
SeaweedFS Go 製の分散ファイルシステム(Apache-2.0) 使える見込み。ただし固定のアクセスキーに、S3 用の設定ファイル(JSON)が別に要る(未検証)
Garage Rust 製の分散ストレージ(AGPL-3.0) 起動後にクラスタの構成の適用とキーの作成が要り、テスト環境の初期化が複雑になる(未検証)
Ceph RGW 大規模向けの統合ストレージ 最低 3 ノードが要り、用途に対して過剰
MinIO をソースからビルド 公式のソースから自前でイメージを作る CI が遅くなる。上流の保守の状況も不透明
MinIO の有償版・認証付きのレジストリ 公式の配布物を、認証付きで取得する 契約と認証情報の管理が要る

テスト専用のモックや分散ストレージは、どれも「CI だけなら動く」か「動くが設定が増える」でした。ローカル開発の GUI と永続化まで満たし、初期化の手順も変えずに済みそうなのは、上の 2 つだけでした。

最後の 2 つは、実機で統合テストを流して比べた

pgsty/minio と RustFS は、どちらも資料の上では要件を満たします。そこで、CI と同じ手順で実際に動かしました。ボリュームを作り直したまっさらな状態でテスト用の Compose を起動し、統合テストを実行します。

観点 pgsty/minio RustFS
統合テスト 通った 通った
既存の mc の初期化スクリプト そのまま動いた そのまま動いた(クライアントは pgsty/mc を使用)
Web の GUI あり。従来の MinIO Console と同じ あり(/rustfs/console/)
データの永続化 あり。従来どおりボリューム あり。ただしコンテナは UID 10001 で動くので、bind mount では権限に注意
必要な変更 イメージ名だけ イメージ名、起動コマンド、認証の環境変数、GUI の URL
挙動の差 無い(MinIO と同じコード) 独自の実装なので、細部が MinIO と違う可能性がある
ライセンス AGPL-3.0 Apache-2.0
持続性 小規模な組織のフォーク(GitHub のスター約 4,000)。Docker Hub のイメージは 2026-08-04 以降更新が無い 大規模なコミュニティ(GitHub のスター約 34,600)。更新が活発
成熟度 MinIO の実績を引き継ぐ GA から約 3 週間

どちらも要件は満たしました。差が出たのは「変更の量」と「挙動が変わるリスク」、そして「持続性」です。

ライセンスも確かめました。AGPL-3.0 は、社内のローカル環境と CI で使うだけなら配布にあたらないので、影響は小さいと判断しています。もともとの公式の MinIO も AGPL-3.0 なので、条件は従来と変わりません。

決定:フォークを採用し、RustFS を切り替え先に決めておく

採用したのは pgsty/minio と pgsty/mc です。理由は 2 つです。

  1. 変更がイメージ名だけで済む。 GUI も永続化も mc の手順もドキュメントも、何も変えずに CI をすぐ戻せます
  2. 挙動が変わらない。 RustFS も実機で要件を満たしましたが、GA から日が浅く、MinIO との細かな挙動の差を見極める時間がありません。今回の目的は CI を早く戻すことなので、挙動が変わらない選択肢を優先しました

一方で、持続性は RustFS の方が上です。そこで、配布が止まったときの切り替え先を、今のうちに決めておきました。

  • フォークの配布が止まったら、または新しい版が Docker Hub に出なくなったら、RustFS に切り替える
  • 手順は、Compose のサーバーを rustfs/rustfs に替え、起動コマンドと認証の環境変数を設定するだけ。初期化は引き続き mc を使える
  • RustFS が安定してきたら、障害が起きる前に移ることも検討する

実機で比べておいたおかげで、切り替えの手順まで具体的に書けています。「いざとなったら RustFS」ではなく、何をどう変えればよいかが分かっている状態です。

フォークに依存するリスクを、イメージの固定で抑える

小規模な組織が配布するイメージに依存すると、新しいリスクが生まれます。配布元のアカウントが乗っ取られるなどして、同じタグのまま中身が差し替えられるリスクです。

そこで、イメージをタグとダイジェストの両方で固定しました。

services:
  test-minio:
    image: pgsty/minio:RELEASE.2026-08-04T00-00-00Z@sha256:b6bfe723…
  test-minio-init:
    image: pgsty/mc:RELEASE.2026-09-16T00-00-00Z@sha256:cfc83108…

ダイジェスト(@sha256:…)は、イメージの中身から計算される値です。中身が差し替えられるとダイジェストが変わるので、一致しないイメージは pull の時点で失敗します。タグも残しているのは、人が読んだときにどの版か分かるようにするためです。

版を上げるときは、依存の更新を自動で PR にするツール(Renovate)の PR を、レビューしてから取り込みます。ダイジェストが変わる更新も、人の目を通ります。

同じ考え方で、GitHub Actions もコミット SHA で固定した

同じ時期に、GitHub Actions の uses: も、タグからコミット SHA に固定しました。

# 変更前
- uses: actions/checkout@v7
# 変更後
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

タグは、配布元が後から別のコミットに付け替えられます。コミット SHA なら、中身が変わりません。末尾のコメントに版を書いておけば、人が読んでも分かり、Renovate もそのコメントを更新してくれます。

依存しているものの中身が、知らないうちに変わらないようにする。イメージのダイジェストと Actions の SHA は、どちらもこのための仕組みです。

はまったところ:古いコンテナが名前でぶつかる

ローカルに、旧イメージで作ったコンテナが残っていると、新しい Compose が起動できません。コンテナ名が同じでぶつかるためです。

docker rm minio minio-init
docker compose up

古いコンテナを消してから起動し直せば解決します。この手順は、判断の記録(ADR)に書いておきました。

まとめ

やったこと 理由
後継を探す前に、使う S3 の機能を洗い出した 比べる観点が「この 5 つが動くか」に絞れる
8 つの選択肢を、要件に照らして比べた モックや分散ストレージは、ローカル開発の体験か設定の量で落ちた
最後の 2 つは、CI と同じ手順で実機で比べた 資料の上では両方満たす。差は動かして初めて分かる
変更が最小で挙動が変わらないフォークを採用した 目的は CI を早く戻すこと
配布が止まったときの切り替え先(RustFS)を先に決めた 持続性はフォークより上。手順まで書いておける
イメージをタグとダイジェストで、Actions をコミット SHA で固定した フォークへの依存で増えた、中身の差し替えのリスクを抑える

学びは 2 つです。

  1. 代わりを探す前に、何が要るかを絞る。 「MinIO の代わり」を探すと、MinIO と同じくらい高機能なものを探してしまいます。実際に要ったのは、5 つの API と path-style と初期化だけでした
  2. 急ぎで選んだものほど、逃げ道を先に決める。 早く戻すために選んだ選択肢には、たいてい持続性の弱さがあります。固定でリスクを抑え、切り替え先と手順を先に書いておけば、次に止まったときに慌てずに済みます

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?