🏞️

Cloud Run で画像リサイズ API を作る

2023/12/22に公開

2023年は「Cloud Run を触って覚える」をテーマとした ひとりアドベントカレンダー を開催しており、Cloud Run のさまざまな機能や Cloud Run でよく使う構成などをご紹介しています。

22日目は Cloud Run で画像リサイズ API を作ってみたので、その手順を解説します。

Cloud Run の概要は「gihyo.jp」で解説していますので、こちらもぜひご覧ください。

https://gihyo.jp/article/2023/10/modern-app-development-on-google-cloud-03

画像リサイズ

今回は Cloud Run で画像をリサイズするシンプルな API を作ってみました。画像のリサイズもできる CDN サービスを使うことが多くなってきていますが、「最小限の構成で画像のリサイズだけしたい」といったようなユースケースに使えるアーキテクチャだと思います。

アーキテクチャ
アーキテクチャ

Cloud Storage バケットに格納しているファイルを、クエリパラメータで自由にリサイズできる API を Cloud Run で構築します。Cloud Storage バケットは Cloud Storage FUSE を使ってマウントし、sharp を使ってリサイズを実施します。Cloud Run の前にアプリケーション ロードバランサを挟み、Cloud CDN を有効化してキャッシュできるようにします。

手順

Cloud Storage バケットを作成する

まずは Cloud Storage バケットを作成します。

作業は Cloud Shell 上で行いますので、まずは Cloud Shell を開きます。

Cloud Shell の起動
Cloud Shell の起動

次のコマンドで Cloud Storage バケットを作成します。BUCKET_NAME は適宜修正してください。

gcloud storage buckets create gs://<BUCKET_NAME> \
  --location asia-northeast1

適当な画像ファイルを数点アップロードしておきます。Cloud Shell に画像をアップロードするには、オプションメニューから [アップロード] を選びます。

アップロード
アップロード

[フォルダ] をクリックし images フォルダを選びます。

フォルダの指定
フォルダの指定

Cloud Shell へのアップロードが完了したら、次のコマンドで画像ファイルをアップロードします。

gcloud storage cp images/* gs://<BUCKET_NAME>/

Cloud Run サービスを作成する

次に Cloud Run サービスを作成します。

サンプルコードを GitHub からクローンします。

git clone git@github.com:suwa-yuki/run-resize-image-sample.git
cd run-resize-image-sample

main.js のコードは次の通りです。filesize をクエリパラメータに取り、指定したファイル名の画像を指定したサイズが長辺となる画像にリサイズします。

main.js
const express = require("express")
const sharp = require("sharp")

const mntDir = process.env.MNT_DIR
const app = express()

app.get("/", async (req, res) => {
  const { file, size } = req.query
  const original = await sharp(`${mntDir}/${file}.jpg`)
  const resized = await original.resize(parseInt(size))
  const data = await resized.toBuffer()
  res.type('jpeg')
  res.send(data)
});

app.listen(3000, () => {
  console.log("Server started on port 3000")
})

サービス アカウントを作成します。Cloud Storage バケットのオブジェクトの読み取り権限を付与します。

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"

次のコマンドでデプロイします。

gcloud alpha run deploy resizer \
  --region asia-northeast1 \
  --source . \
  --port 3000 \
  --execution-environment gen2 \
  --service-account fs-identity \
  --allow-unauthenticated \
  --add-volume=name=gcs,type=cloud-storage,bucket=<BUCKET_NAME> \
  --add-volume-mount=volume=gcs,mount-path=/mnt/gcs \
  --update-env-vars MNT_DIR=/mnt/gcs

Cloud Storage バケットのマウントは --add-volume--add-volume-mount オプションで設定することができます。マウント先は /mnt/gcs にしており、このパスを環境変数 MNT_DIR に設定しています。sharp からは、このパス配下のファイルをオリジナル画像ファイルとしてアクセスしにいきます。

アクセスしてみる

それでは使ってみたいと思います。クエリパラメータとして filesize を受け取るようにしているので、それぞれ指定した URL を作り、ブラウザからアクセスしてみます。

hat という名前のファイルを長辺 300 で取得する場合は、次のような URL になります。

https://<CLOUDRUN_URL>?file=hat&size=300

画像リサイズ API の実行結果
画像リサイズ API の実行結果

好きなサイズで取得できます。

画像リサイズ API の実行結果 (サイズ変更)
画像リサイズ API の実行結果 (サイズ変更)

CDN を追加する

一度リサイズした画像は再度 Cloud Run を経由してリサイズし直す必要はないため、CDN キャッシュを組み合わせると良いです。Google Cloud ではグローバル外部アプリケーション ロードバランサの設定で Cloud CDN を有効化できます。Cloud Run サービスとグローバル外部アプリケーション ロードバランサを接続するには Cloud Run Integration (プレビュー) を使用すると、少ないステップでかんたんにカスタムドメインも含めて設定できます。設定方法は次のブログで紹介しているので参考にしてください。

https://zenn.dev/google_cloud_jp/articles/cloudrun-itg-alb

作成後、ロードバランサのコンソールから編集します。バックエンド サービスの設定で Cloud CDN の設定が行えます。

Cloud CDN の設定
Cloud CDN の設定

各設定の意味は次のドキュメントを参考にしてください。

https://cloud.google.com/cdn/docs/caching?hl=ja

まとめ

パラメータをカスタマイズすれば、ここからさらに機能を持たせることができます。sharp はリサイズだけではなく、切り抜き、回転、合成、エフェクト、色調補正など様々な機能があります。要件に合わせてカスタマイズしながら使ってみてください。

Google Cloud Japan

Discussion