🙆‍♂️

Cloudflare R2で静的ファイルを配信する - CORS設定を添えて -

2022/10/12に公開

【2023年02月13日追記】

コンソールからCORSの設定が出来るようになったようです。

こちらの記事はコンソールから設定できない場合にAPIから設定する方法です。

はじめに

先月にGAとなったCloudflare R2を使って静的ファイルを配信する場合の設定や使用例などを記事に起こしていきます。

【前提条件】

  • Cloudflareのアカウント作成方法については触れませんのでご自身で調べて下さい
  • Cloudflareのコンソール画面を紹介していますが、言語設定を英語にしているため、そのままの紹介です
  • Next.jsを例にビルド済みのJavaScriptやCSSの配信例を記載します
  • 静的ファイルは専用のサブドメインから配信するものとします

まとめ

ざっと記事として言いたいことから

  • public domain accessが使えるようになっているので使用するのが吉
  • AWS S3やGCSと異なり通信量が無料かつ、操作に関しても無料分が存在するのは大きい
  • Cloudflareを使用しているならば使用することを前提に考えてよい

静的ファイルの配信

今回はNext.jsを例に記載します。(正直なんでもいい)
Webアプリケーションを配信する上でHTMLはもちろん、JavaScriptやCSSなどの静的ファイルの配信もかかせません。Next.jsであればビルドしたものをアプリケーションサーバ内に配置してアプリケーションサーバと同居しているWebサーバから配信することも可能です。しかし、これには何点か不都合なことが存在します。

  • Webサーバにhttpリクエストが集中する
  • コンテナで構築されたインフラでデプロイする場合に旧リソースへのアクセスが404となる

などなど挙げればキリがないですが、アプリケーションサーバと静的ファイルを配信するサーバは分けておいた方が無難なことが多いです。そこでAWS S3やGCSなどから配信することが多かったのですが、今回はCloudflare R2を使用して静的ファイルの配信やその利点を紹介していきます。

Cloudflareの設定

Cloudflare側の設定について記載していきます。

バケットの作成

バケットの作成はAWS S3 SDKからも作成できますが、動的に作成する必要はないのでCloudflareのコンソール上からサクッと作成してしまいます。

まずはCloudflareのコンソールから「アカウント」→「R2」を選択して、この画面まで来ます。ここに来た場合に課金画面が表示される場合は対応しておいてください。(無料範囲が大きいといっても越えた場合に自動的に課金される仕組み上クレカなどの登録が必要です)
「Create Bucket」ボタンを押してバケット作成画面に行きます。

任意のバケット名を入力し、「Create Bucket」ボタンをクリックするとバケットが作成されます。

配信ドメインの設定

バケットを作成しただけでは、配信が行えません。そこでpublic配信を行うためにドメインの設定を行います。

「Setting」タブから「Bucket Access」の「Connect Domain」ボタンをクリックします。

配信したいドメインを入力して「Continue」ボタンをクリックすると確認画面が表示されます。

「Connect domain」ボタンをクリックするとCNAMEでDNSの設定が完了します。

バケットへのアクセスを可能とする認証情報の設定

バケットを作成しただけ、配信するファイルを設定は別途必要です。そこでバケットにアクセスするための認証情報を設定しておく必要があります。

R2のトップページから「Manage R2 API Tokens」のリンクをクリックします。

「Create API Token」ボタンをクリックして、認証情報の作成を行います。

権限と有効期限を設定します。権限は「Edit」を選択し、有効期限は必要な期間を設定します。R2だけ無期限って設定できないんだけど、これってなんとかならないのか?とかは思っております。 "Custom" を選べば無制限に出来ました。初期はなかった気がするけど、いつ出来るようになった?
設定後に再度「Create API Token」ボタンをクリックするとR2への認証情報が作成されます。

ここに表示されている「Access Key ID」と「Secret Access Key」はこれ以降表示されませんのでメモしておきます。

CORSの設定

これがなくても静的ファイルの配信自体は行えます。しかし、サブドメインから配信する場合にCORSの設定がないとブラウザがエラーを吐きます。Cloudflare R2もAWS S3同様にCORSの設定が行えるのでその方法を記載します。

と前書きを偉そうに説明していますが、Cloudflare R2はAWS S3とは違いコンソールからの設定に現時点(2022年10月12日)では対応していません。そこでREST APIを叩いて設定する必要があります。これはAWS S3と同様です。

ただし、AWS S3もCloudflare R2も同様なのですが、REST APIを叩くには認証情報が必要なのですが、その設定が面倒なんです。何が面倒ってリクエストヘッダーに付与する認証情報はSignature Version 4というルールに基づき設定する必要があります。

認証情報を作成するが面倒なので、Postmanという認証情報を作成してもらいつつ、リクエストするツールを使用します。Postmanにはネイティブ版もありますが、今回はWeb版を使用します。

Cloudflare R2に設定するリクエスト先は https://<bucket-name>.<cloudflare account id>.r2.cloudflarestorage.com/?cors に向けて PUT リクエストで送信します。

続いて認証情報を生成するための設定を行います。「Type」に「AWS Signature」を設定します。「AccessKey」と「SecretKey」はバケットにアクセスするための作成した認証情報の「Access Key ID」と「Secret Access Key」を設定します。最後に「Service Name」に「s3」の設定が必要です。

最後にCORSを許可するXML設定を「Body」に設定します。

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedOrigin>*</AllowedOrigin>
  </CORSRule>
</CORSConfiguration>

今回はGETとHEADはどのドメインからもアクセスを許可する設定にしています。この設定で「Send」ボタンをクリックして200が返ってくると設定が完了です。

アプリケーションの設定

続いてアプリケーションに必要な設定を記載していきます。

CDNから静的ファイルを取得する

Next.jsには assetPrefix という設定が存在し、静的ファイルの取得先を設定することができます。それを設定しておきます。

module.exports = {
  assetPrefix: process.env.ASSET_PREFIX,
}

環境変数 ASSET_PREFIX が設定された状態でビルドすることで静的ファイルが設定されたドメインから取得するようになります。例えばデプロイごとに配信パスを変更する場合は ASSET_PREFIX
https://<static-subdomain>.<your domain>/<コミットのSHA>という風な設定をしておくと、デプロイ時に新旧が混在する場合も対応が可能になります。

ビルドしたファイルをバケットにアップロードする

最後にビルドしたファイルをバケットにアップロードします。Cloudflare R2はAWS S3互換なのでAWS CLIでアップロードが可能です。なのでNext.jsのビルドしたファイルをアップロードするには以下のシェルを実行することになります。

$ export AWS_ACCESS_KEY_ID=<your Access Key ID>
$ export AWS_SECRET_ACCESS_KEY=<your Secret Access Key>
$ export AWS_EC2_METADATA_DISABLED=true
$ aws s3 --endpoint-url https://<your cloudflare account id>.r2.cloudflarestorage.com cp .next/static s3://<your bucket name>/<コミットのSHA>/_next/static --recursive

これでCloudflare R2にビルドされたファイルがアップロードされれば完了です。

Cloudfalre R2の料金

Cloudflare R2って使えるのはわかったけどお高いの?って方向けのおまけです。料金は
このページ
に書いてるんですが、時間がない人向けにサクッと説明すると

  • 10GBまでバケットにファイルを保存しても無料
  • ファイルをアップロードするなどの操作も2パターン存在するが100万回までは無料
  • 配信する時にかかる通信量は無料

とまぁ、無料の範囲が非常に大きいです。AWS S3とかGCSは保存容量にかかる金額もそうですが、アップロードする場合の料金もちょくちょく乗ってくるのですが、Cloudflare R2はそれがないです。

最後に

Cloudflare R2が発表された時に書かれた記事の通り料金は非常に安価なものになっています。GA前はCloudflare Workers経由でしかアクセスが出来なかったものがDomain accessに対応したことによって使い勝手は普段使いが行えるくらいまで昇華されたと言って過言ではないと思います。
Cloudflareを使用している方はぜひ使用してみてはいかがでしょうか。

Discussion