「画像管理の重力」をCloudflare R2で消し去る。自動アップロードの実装ガイド

5 分で読めます

目次

ブログ執筆において、画像の用意と管理は最大の「重力」です。キャプチャを取り、リサイズし、ストレージに上げて、URLを貼る。この摩擦が、書く意欲をじわじわと削ぎ落としていきます。

この記事は、「ブログ執筆システムを自作・拡張しているエンジニア」を対象としています。単に Blogger の管理画面から画像を貼る人ではなく、Markdown からの自動投稿パイプラインを構築し、そこで発生する画像のアップロードと置換の摩擦をゼロにしたい方のためのガイドです。

なぜ Cloudflare R2 なのか

最大の理由は 「配信コストが無料(Egress 0円)」 である点です。エンジニアにとって、既存の S3 互換ツール(boto3など)がそのまま使え、どれだけ画像が見られてもストレージ料金以外が発生しない R2 は、コストを気にせず画像を放り込める「聖域」として最適です。

セットアップの「急所」攻略

R2 の設定は S3 に似ていますが、Cloudflare 独自の UI 構造により、いくつか迷いやすいポイントがあります。

1. バケットの作成

まずは受け皿となるバケットを作成します。

R2バケット作成画面:位置情報は『自動』、クラスは『Standard』でOK

R2バケット作成時の推奨設定

名前を決め、位置情報を 「自動(アジア太平洋)」 、ストレージクラスを 「Standard」 に設定して進めれば問題ありません。

2. 公開ドメインの接続

バケットの中身を外から見えるようにするために、ドメインを紐付けます。ここが最初の迷いどころです。

R2バケットの設定画面:『公開アクセス』セクションにある『カスタムドメイン』を探す

『R2 > バケット詳細 > 設定 > カスタムドメイン』から進むのが正解

Cloudflare のサイドメニューにある一般的な「ドメイン」から設定しようとすると、無関係な DNS スキャンなどが始まってしまいます。正解は、「R2 > バケット詳細 > 設定 > カスタムドメイン」 という、バケット個別の設定画面から接続することです。

3. APIトークンの場所

スクリプトから操作するための「鍵」を発行します。このメニューは少し深い場所にあります。

APIトークンの隠れ場所:R2トップの最下部『Account Details』にあるManageボタン

APIトークン管理画面への入り口

R2 トップ画面の最下部にある 「Account Details」 セクションの右端、「Manage」 ボタンの中に隠れています。

4. 権限設定

発行画面では 「アカウント API トークン」 (上側)を選択します。

権限設定の正解:『オブジェクト読み取りと書き込み』を選択し、管理者権限は不要

自動同期に必要な最小限の権限設定

ここで最も重要なのがアクセス許可です。デフォルトの「読み取り専用」ではアップロードができません。必ず 「オブジェクト読み取りと書き込み」 を選択してください。

5. 情報の確保

発行完了画面に一度だけ表示される「3点セット」を控えます。

秘密の鍵:発行直後にしか表示されない3つの重要情報(ID、シークレット、エンドポイント)

発行された認証情報は即座にメモが必要

  • アクセスキー ID
  • シークレットアクセスキー
  • S3エンドポイント (S3 API)

実装:システムへの組み込み

取得した情報を環境変数に落とし込み、プログラムから呼び出します。

1. .env の記述例

.env に、汎用的な形式で値を保存します。


# Cloudflare R2 Settings
R2_ACCESS_KEY_ID=xxx (アクセスキーID)
R2_SECRET_ACCESS_KEY=yyy (シークレットアクセスキー)
R2_ENDPOINT_URL=https://<account_id>.r2.cloudflarestorage.com
R2_BUCKET_NAME=my-bucket-name
R2_PUBLIC_URL_PREFIX=https://static.example.com/

2. 最小構成コード

boto3 を使って R2 に接続し、ファイルをアップロードする最小限の Python コードです。


import boto3
import os

# S3互換クライアントの作成
s3 = boto3.client(
    's3',
    endpoint_url=os.getenv('R2_ENDPOINT_URL'),
    aws_access_key_id=os.getenv('R2_ACCESS_KEY_ID'),
    aws_secret_access_key=os.getenv('R2_SECRET_ACCESS_KEY'),
    region_name='auto'
)

# ファイルのアップロード
s3.upload_file(
    'images/1.png', 
    os.getenv('R2_BUCKET_NAME'), 
    'images/00006/1.png',
    ExtraArgs={'ContentType': 'image/png'}
)

自動化のワークフロー

セットアップが終われば、あとはパイプラインの構築です。私は各記事のディレクトリに images.yaml という「画像メモ」を置き、images/ フォルダに画像を置くだけの運用にしています。

執筆中は [[img:1]] のようにプレースホルダーを書くだけ。投稿時に以下のフローを自動実行します。

  1. URL置換と保護: [[img:1]] を R2 の URL に置換。ただし、説明文としての [[img:1]] がコードブロック内にある場合は置換をスキップします。
  2. キャッシュ対策: 画像 URL の末尾に更新日時のタイムスタンプ(?v=...)を付与し、画像差し替えがブラウザに即座に反映されるようにします。
  3. クリーンアップ: images.yaml に定義されていない古い画像ファイルを R2 から自動削除し、ストレージを常にクリーンに保ちます。

まとめ

仕組みを整える目的は、常に一つ。「明日もまた、一行でも多く書くため」

Cloudflare R2 という低コストなインフラと、自動化の仕組みを組み合わせる。この工夫の積み重ねが、読者にとっても、書き手にとっても心地よい執筆環境を作り上げます。

コメント

コメントは無効になっています。