PenpotとAWS S3・Cloudflare R2連携:セルフホスト環境における画像アセット外部ストレージ移行とコスト削減の極意
テックリードの君なら、チームでPenpotのセルフホスト環境(Docker)を立ち上げた瞬間に「おや?」と気づいたはずだ。そう、デフォルトのままだと、デザイナーやエンジニアがアップロードした膨大な画像アセットは、すべてコンテナ内のローカルファイルシステム、あるいはバインドマウントされた単一のホストディレクトリに書き込まれていく。
PoCの段階ならそれでいい。しかし、デザインシステムが成熟し、チームの規模が拡大し、マルチインスタンス(オートスケーリング)による高可用性構成を組んだ瞬間、この「ローカルストレージ依存」は致命的なボトルネックになる。インスタンスAにアップロードされた画像が、ロードバランサーの背後にあるインスタンスBから見えない――いわゆる「消えるアセット問題」の始まりだ。
今回は、Penpotのセルフホスト環境におけるストレージアーキテクチャを根本から覆し、AWS S3またはCloudflare R2(S3互換ストレージ)へアセットを完全オフロードする方法を解説する。単なる環境変数の書き換えではない。マルチテナントを見据えた堅牢なインフラ設計と、チームの生産性を極限まで高めるプロトタイピングのワークフローを同時に手に入れよう。
—
1. なぜS3 / R2への移行が必須なのか?(アーキテクチャの真実)
Penpotのバックエンド(Clojure製)は、アセット管理において非常にクリーンな抽象化レイヤーを持っている。しかし、デフォルトのDocker Compose構成では、これがローカルのファイルストレージドライバに結びついている。
これをS3互換ストレージに切り替えることで、以下の3つの圧倒的なメリットが手に入る。
1. 水平スケーリング(Horizontal Scaling)の解放:
Dockerコンテナをいくつ並べようとも、背後のS3/R2が単一の真実の情報源(Single Source of Truth)となるため、インスタンス間でストレージを同期させる無駄な苦労が消え去る。
2. コストの劇的最適化(特にCloudflare R2の活用):
AWS S3と比較して、Cloudflare R2は「エグレス料金(転送料金)が完全無料」だ。デザインツールはプレビューや高解像度画像の読み込みで帯域を食い潰しがちだが、R2をストレージバックエンドに据えることで、ランニングコストを限界まで削ぎ落とせる。
3. バックアップと災害復旧(DR)の簡素化:
コンテナの永続化ボリューム(PVC)のバックアップに怯える必要はない。アセットはすべてオブジェクトストレージに存在するため、コンテナ自体はいつでもスクラップ&ビルド可能な「ステートレス」な存在になる。
—
2. 実践:Penpot Docker環境におけるS3/R2ストレージ設定
それでは、実際の環境構築に移ろう。Penpotのバックエンド(`penpot-backend`)は、環境変数を通じてS3互換ストレージをネイティブにサポートしている。
以下の `docker-compose.yml` のスニペットは、Cloudflare R2(またはAWS S3)をバックエンドに指定するためのプロダクションレディな設定例だ。
version: “3.8”
services:
penpot-backend:
image: penpot/backend:latest
restart: always
environment:
- PENPOT_PUBLIC_URI=https://design.yourcompany.internal
# データベース接続設定
- PENPOT_DATABASE_URI=postgresql://penpot:penpot_secret@penpot-postgres:5432/penpot
- PENPOT_REDIS_URI=redis://penpot-redis:6379
# — アセットストレージの外部化設定 (S3 / R2) —
# ストレージプロバイダとして “s3” を明示的に指定
- PENPOT_STORAGE_BACKEND=s3
# S3互換ストレージのエンドポイント
# AWS S3の場合は省略可能だが、Cloudflare R2やMinIOの場合は必須
# 例: Cloudflare R2の場合 -> https://
- PENPOT_S3_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
# 接続先のバケット名
- PENPOT_S3_BUCKET=penpot-assets-production
# 認証情報 (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY 相当)
- PENPOT_S3_ACCESS_KEY=your_r2_or_s3_access_key_id
- PENPOT_S3_SECRET_KEY=your_r2_or_s3_secret_access_key
# リージョン設定 (R2の場合は “auto” で動作することが多い)
- PENPOT_S3_REGION=auto
# パススタイルアクセスを使用するかどうか (R2やMinIOでは true が必須)
- PENPOT_S3_FORCE_PATH_STYLE=true
depends_on:
- penpot-postgres
- penpot-redis
networks:
- penpot-net
# その他のサービス (frontend, postgres, redis, etc.) は省略
💡 現場の罠:パススタイルアクセス(Path-style access)の重要性
AWS S3以外のストレージ(Cloudflare R2, MinIO, LocalStackなど)を使う場合、`PENPOT_S3_FORCE_PATH_STYLE=true` の指定を忘れると、クライアントライブラリが仮想ホストスタイル(`bucket.endpoint/key`)でリクエストを送り、名前解決エラーや403 Forbiddenの泥沼にハマる。S3互換ストレージを使う際の鉄則として覚えておいてほしい。
—
3. 開発スピードを劇的に高めるプロのシークレット・テクニック
ストレージ基盤が安定したところで、Penpotを日々使い倒すエンジニアとデザイナーの生産性を引き上げる「隠し味」を共有しよう。
⌨️ 開発スピードを限界突破させるキーボードショートカット
マウスクリックはデザイナーの時間を奪う悪魔の所業だ。以下のショートカットをチームの標準語にせよ。
- `Shift + R`: フレーム(Frame)作成モード。コンポーネントの親枠を瞬時に切る。
- `Alt + 1`: レイヤーパネルのフォーカス。マウスを動かさずに構造へアクセス。
- `Ctrl/Cmd + /`: クイックアクション。コマンドパレットからあらゆる機能やプラグインを爆速で呼び出す。
- `V` (選択) と `K` (スケール) のトグル: デザインシステム内の要素を比率を維持したままリサイズする際、`K`への切り替えを指に覚え込ませることでレイアウト崩れを防ぐ。
🔌 絶対入れるべき神プラグイン(および活用思想)
Figmaからの移行組が最初に絶望するのは「プラグインエコシステムの差」だが、Penpotも拡張性を急速に高めている。特にチーム開発で導入すべきは以下のカテゴリだ。
1. Design Tokens Exporter:
デザインシステムの色定義、タイポグラフィ、スペーシングをJSONとしてエクスポートし、GitHub Actions経由でiOS/Android/Webのコードリポジトリへ自動同期するパイプラインの起点とする。
2. Accessibility (a11y) Checker:
コントラスト比(WCAG 2.1)をリアルタイムで検証し、アクセシビリティの負債を上流のデザイン工程で焼き払う。
—
4. チーム開発で役立つ設定の共有化ルール
セルフホスト環境を運用するテックリードとして、ツールの「野良運用」を防ぐためのガバナンス設計は避けて通れない。
1. チームとライブラリの厳格なスコープ分離:
Penpotの「Shared Libraries」機能を活用し、全社共通のUIコンポーネント(Primitive)と、プロダクト個別のビジネスロジックを含むコンポーネントを明確に分離する。プロジェクトごとにライブラリへのリンク権限を絞り、意図しない破壊的変更を防ぐ。
2. アセット命名規則のCI/CD連携:
外部ストレージ(S3/R2)にアップロードされる画像アセットがカオス化するのを防ぐため、チームメンバーにはSVGやWebPの最適化(SVGO等を通したクリーンアップ)を義務付けるガイドラインを策定する。
—
5. 結び:ツールを使いこなすのではなく、インフラからデザインをハックせよ
Penpotのようなオープンソースの強力なツールをセルフホストし、AWS S3やCloudflare R2といったモダンなクラウドインフラストラクチャと結合させること。それは単に「お金を節約する」ためではない。
自分たちのデザインアセット、自分たちのデータ、自分たちのワークフローの主権を完全に掌握するということだ。
このアーキテクチャを導入した瞬間から、あなたのチームのプロトタイピング環境は、インフラの制約から完全に解放される。さあ、今すぐ `docker-compose.yml` を書き換え、真のスケーラブルなデザインOpsを手に入れよう。