本記事の執筆にはAIを使用しています。
はじめに
Google Cloud Storage(以下、GCS)のエミュレーターである fake-gcs-server の用途と使い方を紹介します。
Dockerで独立したサーバーとして起動する方法と、Goのテストに組み込む方法を扱います。
「fake-gcs-server」とは?
GCS APIをローカル環境で再現するエミュレーターです。
次の3通りの形で使えます。
- Dockerイメージ
- 実行バイナリ
- Goパッケージ
JSON APIとXML APIの主な操作に対応しています。
本物のGCSと完全に同じではないため、本番環境へリリースする前にはGCSに対するテストも行いましょう。
環境
- Docker: 29.5.2
- Go: 1.25.5
- fake-gcs-server: 1.56.1
用途
GCSを使う処理の自動テスト
バケットとオブジェクトの作成、取得、更新、削除をローカルでテストできます。
CIでGCPのクレデンシャルを配布する必要がありません。
ローカル開発
開発中のアプリから、実際のGCSの代わりに接続できます。
クラウドへの通信と課金を発生させずに、ファイル操作を確認できます。
初期データを使う結合テスト
ディレクトリをマウントして、バケットとオブジェクトを起動時に読み込めます。
毎回同じ状態からテストを始めたいときに便利です。
基本的な使い方
Dockerで起動する
ここでは、curl やクライアントライブラリから扱いやすいHTTPで起動します。
$ docker run --rm --name fake-gcs-server \
-p 4443:4443 \
-e FAKE_GCS_SCHEME=http \
fsouza/fake-gcs-server:1.56.1
起動したら、ヘルスチェックを呼び出します。
$ curl -i http://localhost:4443/_internal/healthcheck
バケットの一覧はGCS JSON APIのエンドポイントから取得できます。
$ curl http://localhost:4443/storage/v1/b
HTTPSで起動する場合は FAKE_GCS_SCHEME を省きます。
既定では自己署名証明書が使われるため、curl での確認時は --insecure が必要です。
初期データを読み込む
データを「バケット名/オブジェクト名」の構成で配置します。
data/
└── sample-bucket/
└── hello.txt
data ディレクトリをコンテナーの /data へマウントします。
$ docker run --rm --name fake-gcs-server \
-p 4443:4443 \
-e FAKE_GCS_SCHEME=http \
-v "$(pwd)/data:/data" \
fsouza/fake-gcs-server:1.56.1
公式Dockerイメージは -data /data を起動引数に指定しています。
そのため、Dockerで初期データを使うときは /data へマウントするのが簡単です。
バケットとオブジェクトを確認します。
$ curl http://localhost:4443/storage/v1/b
$ curl http://localhost:4443/storage/v1/b/sample-bucket/o
Goのテストに組み込む
Goでは fakestorage パッケージを使い、同じプロセス内にサーバーを起動できます。
パッケージを追加します。
$ go get github.com/fsouza/fake-gcs-server/fakestorage@v1.56.1
NewServer() へ初期オブジェクトを渡し、Client() からエミュレーター用のGCSクライアントを取得します。
package storage_test
import (
"context"
"io"
"testing"
"github.com/fsouza/fake-gcs-server/fakestorage"
)
func TestDownloadObject(t *testing.T) {
server := fakestorage.NewServer([]fakestorage.Object{
{
ObjectAttrs: fakestorage.ObjectAttrs{
BucketName: "sample-bucket",
Name: "hello.txt",
},
Content: []byte("Hello, GCS!"),
},
})
t.Cleanup(server.Stop)
reader, err := server.Client().
Bucket("sample-bucket").
Object("hello.txt").
NewReader(context.Background())
if err != nil {
t.Fatal(err)
}
defer reader.Close()
content, err := io.ReadAll(reader)
if err != nil {
t.Fatal(err)
}
if got, want := string(content), "Hello, GCS!"; got != want {
t.Errorf("content = %q, want %q", got, want)
}
}
server.Client() は、サーバー内部のモック通信を使う storage.Client を返します。
TCPポートやGCPのクレデンシャルは不要です。
起動方法を詳細に変えたい場合は NewServerWithOptions() を使います。
環境変数の一覧
すべてのサーバー起動オプションは、FAKE_GCS_ で始まる環境変数で指定できます。
起動引数と環境変数の両方を指定した場合は、起動引数が優先されます。
| 環境変数 | 起動引数 | 既定値 | 説明 |
|---|---|---|---|
FAKE_GCS_BACKEND |
-backend |
filesystem |
保存先。filesystem または memory
|
FAKE_GCS_FILESYSTEM_ROOT |
-filesystem-root |
/storage |
filesystem バックエンドの保存先 |
FAKE_GCS_PUBLIC_HOST |
-public-host |
storage.googleapis.com |
公開URLとXML APIで使うホスト |
FAKE_GCS_EXTERNAL_URL |
-external-url |
サーバーの起動URL | 再開可能なアップロードの Location ヘッダーに返すURL |
FAKE_GCS_SCHEME |
-scheme |
https |
通信方式。http、https、both
|
FAKE_GCS_HOST |
-host |
0.0.0.0 |
サーバーがバインドするホスト |
FAKE_GCS_DATA |
-data |
空 | 初期データを読み込むディレクトリ |
FAKE_GCS_CORS_HEADERS |
-cors-headers |
空 | CORSで許可する追加ヘッダー。複数指定はカンマ区切り |
FAKE_GCS_PORT |
-port |
4443 |
HTTPSのポート。HTTPのみの場合もこの値を使用 |
FAKE_GCS_PORT_HTTP |
-port-http |
8000 |
both のときにHTTPで使うポート |
FAKE_GCS_EVENT_PUBSUB_PROJECT_ID |
-event.pubsub-project-id |
空 | イベントの送信先Pub/SubプロジェクトID |
FAKE_GCS_EVENT_PUBSUB_TOPIC |
-event.pubsub-topic |
空 | イベントの送信先Pub/Subトピック |
FAKE_GCS_EVENT_BUCKET |
-event.bucket |
空 | イベントの対象を限定するバケット |
FAKE_GCS_EVENT_OBJECT_PREFIX |
-event.object-prefix |
空 | イベントの対象を限定するオブジェクト名の接頭辞 |
FAKE_GCS_EVENT_LIST |
-event.list |
finalize |
通知するイベント。finalize、delete、metadataUpdate、archive をカンマ区切りで指定 |
FAKE_GCS_LOCATION |
-location |
US-CENTRAL1 |
バケットのロケーション |
FAKE_GCS_CERT_LOCATION |
-cert-location |
空 | HTTPSサーバーの証明書ファイル |
FAKE_GCS_PRIVATE_KEY_LOCATION |
-private-key-location |
空 | HTTPSサーバーの秘密鍵ファイル |
FAKE_GCS_LOG_LEVEL |
-log-level |
info |
ログレベル。debug、info、warning、warn、error
|
FAKE_GCS_PORT や FAKE_GCS_PORT_HTTP に数値以外を指定すると、サーバーはエラーで終了します。
使える起動引数は、次のコマンドでも確認できます。
$ docker run --rm fsouza/fake-gcs-server:1.56.1 -help
注意点
fake-gcs-server はGCSの代替サーバーではなく、開発とテスト用のエミュレーターです。
例えば署名付きURLは利用できますが、署名や有効期限などのクエリーパラメーターは検証されません。
認証、権限、署名の正しさを確認するテストは、本物のGCSに対して実施してください。
おわりに
fake-gcs-server を使うと、GCSを使う処理をローカルやCIで手軽にテストできます。
他言語と共通で使うならDocker、Goのテスト内で完結させるなら fakestorage パッケージが便利です ![]()