画像配信サーバーをCloud RunとCloud Storage FUSEで構築する

はじめに
今回は、画像配信サーバーをセルフホストしたいと思います。 単に、画像を配信するだけでなく、画像のリサイズや、画像の圧縮などを行いたいです。 また、この記事ではCDNをつかいませんが、CDNをつかうとオリジンへのアクセスは減るりますので、サーバーレスで構築したいと思います。 そこで、今回は、IPXとCloud RunとCloud Storage FUSEを使って、画像配信サーバーを構築していきます。
IPXとは
High performance, secure and easy to use image proxy based on Sharp and libvips.
IPXは、画像のリサイズや、画像の圧縮などを行うことができる画像プロキシです。 IPXは、Nuxt.jsのImageモジュールのデフォルトの画像プロキシとしても使われています。
Cloud Storage FUSEとは
Cloud Storage FUSE は、Cloud Storage バケットをローカル ファイル システムとしてマウントしてアクセスできるようにする FUSE アダプタです。これにより、アプリケーションは、標準のファイル システムのセマンティクスを使用して、バケット内のオブジェクトの読み取りと書き込みを行うことができます。Cloud Storage FUSE は、Google がサポートするオープンソース プロダクトです。
チュートリアル: Cloud Run での Cloud Storage FUSE の使用 を参照すると、Cloud Runの第2世代の実行環境では、Cloud Storage FUSEを利用することができます。
IPXのコード
コードは、下記のリポジトリに配置してあります。
https://github.com/cloudandbuild/blog-article-resources/tree/main/content/blog/article-20230916
IPXのコードは、下記のようになります。 簡単ですね。IPXをミドルウェアとしてHTTPサーバーを立てるだけです。
// index.mjs
import { createServer } from 'node:http';
import { createIPX, createIPXMiddleware } from 'ipx';
import { createApp, fromNodeMiddleware, toNodeListener } from 'h3';
const ipx = createIPX({});
const ipxMiddleware = createIPXMiddleware(ipx);
const app = createApp().use('/', fromNodeMiddleware(ipxMiddleware));
createServer(toNodeListener(app)).listen(process.env.PORT || 8080);
ローカルで起動する場合は、下記のように実行します。
npm i
npm start
適当な画像を配置して、アクセスできることを確認します。
mkdir static
curl -s -o static/cat.jpg 'http://placekitten.com/200/300'
# ブラウザで確認
# original
http://localhost:8080/_/static/cat.jpg
# rotate
http://localhost:8080/rotate_45/static/cat.jpg
参考
https://github.com/unjs/ipx/tree/v1#examples
インフラ構成
主に下記の記事を参考にさせていただきました。
https://cloud.google.com/run/docs/tutorials/network-filesystems-fuse?hl=ja#ship-code
Cloud Storage バケットを作成
gsutil mb -l <REGION> gs://BUCKET_NAME
バケットへのアクセス権をサービス アカウントに付与
gcloud iam service-accounts create fs-identity
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member "serviceAccount:fs-identity@<PROJECT_ID>.iam.gserviceaccount.com" \
--role "roles/storage.objectAdmin"
コンテナ イメージをビルドして Cloud Run にデプロイ
gcloud run deploy filesystem-app --source . \
--execution-environment gen2 \
--allow-unauthenticated \
--service-account fs-identity \
--update-env-vars BUCKET=<BUCKET_NAME>
動作確認
バケットに適当な画像を配置して、アクセスできることを確認します。
FUSEでマウントするディレクトリは、./gcs
としているので、下記のようにアクセスします。
https://<cloud run domain>/_/gcs/cat.jpg
まとめ
今回は、IPXとCloud RunとCloud Storage FUSEを使って、画像配信サーバーを構築してみました。簡単に構築できましたね。 サーバーレスなので、サーバーの管理も不要ですし、アクセスがなければコストも発生しません。(Cloud Storageの画像保存にかかるコストは発生しますが)
次回は、CDNを配置して配信を高速化してみたいと思います。
