【入門編】Penpotのセルフホスト環境におけるRedisを活用したセッション共有とスケールアウト構成の構築手順 – UI/UX・デザインツール活用バイブル

こんにちは!プロダクトデザイナー、そしてエンジニアの皆さん。
日々、Figmaなどのクラウド型デザインツールを使ってチームで画面設計をしていることと思います。素晴らしいツールですよね。しかし、ふとこんな不安が頭をよぎったことはありませんか?

「自分たちのデザインデータ、本当に外部のクラウドサーバーに置きっぱなしにして大丈夫か?」
「セキュリティ要件が厳しいクライアント案件でも、Figmaと同じようにモダンなコンポーネント指向のプロトタイピングがしたい……」

そんな悩みを一発で解決してくれるのが、オープンソース(OSS)の次世代デザイン・プロトタイピングツール「Penpot」です。完全なセルフホストが可能で、SVGをネイティブフォーマットとして採用しているため、開発者とデザイナーの距離を極限まで縮めてくれるモンスターツールです。

今回は、このPenpotを単なるローカルお遊び環境から、「複数台のサーバーで負荷分散(スケールアウト)させ、企業ユースに耐えうる頑健なプロダクション環境」へと進化させるための極意を伝授します。

これをマスターすれば、あなたのチームのインフラ運用の幅が劇的に広がり、どれだけ巨大なデザイン組織になってもビクともしない堅牢なプロトタイピング基盤が手に入りますよ。一緒に見ていきましょう!

—

1. なぜPenpotの「スケールアウト」と「Redis」が必要なのか?

まずは、デザインツールをインフラの観点から少しだけ深掘りします。

Penpotは、従来の静的なお絵描きツールとは違います。デザイナーがコンポーネントを動かし、コメントを残し、プロトタイプをプレビューするその裏側では、「WebSocket」を用いたリアルタイムの双方向通信が常時行われています。

単一コンテナの限界

公式ドキュメントにある通り、Docker Composeでサクッと立ち上げる方法は、開発初期や検証には最高です。しかし、チームの人数が50人、100人と増えていき、全員が同時に巨大なデザインファイルを触り始めるとどうなるでしょう?

  • 単一のサーバー(コンテナ)のCPUやメモリが枯渇する。
  • サーバーが落ちた瞬間、全員の作業セッションが吹き飛ぶ。

Redisによるセッション共有とスケールアウトの魔法

ここで登場するのがRedisです。
複数台のPenpotサーバー(バックエンドコンテナ)をロードバランサー(NginxやAWS ALBなど)の配下に並べたとき、サーバーAに接続していたユーザーが、次の瞬間にサーバーBにルーティングされることがあります。

もしサーバー間でセッション情報が共有されていなければ、ユーザーは「ログインし直し」を余儀なくされ、リアルタイム共同編集の同期が崩壊します。
ここでRedisを「セッションストア兼メッセージブローカー」として中央集権的に配置することで、どのサーバーにリクエストが来ても、シームレスに同じセッションとリアルタイム状態を維持できる——これが、今回構築するスケールアウト構成の正体です。

—

2. 全体アーキテクチャの把握

今回構築するプロダクション環境のトポロジーは以下の通りです。

[ ユーザー / ブラウザ ]
│
▼ (HTTPS / WSS)
┌──────────────┐
│ ロードバランサ │ (Nginx / ALB 等)
└──────┬───────┘
│
┌────┴────────┐
▼ ▼
┌─────────┐ ┌─────────┐
│ Penpot │ │ Penpot │ (App Server 1 & 2: スケールアウト)
│ Node 1 │ │ Node 2 │
└────┬────┘ └────┬────┘
│ │
└──────┬──────┘
▼
┌─────────────┐
│ Redis │ ← セッション共有 & Pub/Sub
└─────────────┘
│
▼
┌─────────────┐
│ PostgreSQL │ ← 永続化データ
└─────────────┘

美しく、そして堅牢な構成ですね。それでは実際に、この環境を構築していきましょう。

—

3. 実践:Docker Composeによるマルチコンテナ・スケールアウト構成

ここでは、単一ホスト上での複数インスタンス起動(および別ホストへ展開する際のベースとなる)Docker Compose構成を組み立てます。

プロジェクトディレクトリに `docker-compose.yml` を作成し、以下の設定を記述してください。各行の意図が手に取るようにわかるよう、丁寧なコメントを入れています。

`docker-compose.yml`

version: ‘3.8’

services:
# —————————————————————————
# 1. データベース層 (PostgreSQL)
# —————————————————————————
postgres:
image: postgres:15-alpine
restart: always
environment:

  • POSTGRES_DB=penpot
  • POSTGRES_USER=penpot
  • POSTGRES_PASSWORD=penpot_secure_password # 本番では必ず強固なパスワードに変更してください

volumes:

  • pgdata:/var/lib/postgresql/data

networks:

  • penpot-net

# —————————————————————————
# 2. セッション管理 & メッセージブローカー層 (Redis)
# —————————————————————————
redis:
image: redis:7-alpine
restart: always
command: redis-server –save 60 1 –loglevel warning
volumes:

  • redisdata:/data

networks:

  • penpot-net

# —————————————————————————
# 3. Penpot フロントエンド・バックエンド統合コンテナ (インスタンス 1)
# —————————————————————————
penpot-frontend-1:
image: penpotapp/frontend:latest
restart: always
ports:

  • “8001:8080” # ホスト側ポートを分けておく

environment:

  • PENPOT_PUBLIC_URI=http://localhost:8080 # ロードバランサーのURLを指定
  • PENPOT_DATABASE_URI=postgresql://postgres:penpot_secure_password@postgres:5432/penpot
  • PENPOT_REDIS_URI=redis://redis:6379/0 # Redisとの接続設定がセッション共有の鍵!
  • PENPOT_TELEMETRY_ENABLED=false

depends_on:

  • postgres
  • redis

networks:

  • penpot-net

# —————————————————————————
# 4. Penpot フロントエンド・バックエンド統合コンテナ (インスタンス 2: スケールアウト用)
# —————————————————————————
penpot-frontend-2:
image: penpotapp/frontend:latest
restart: always
ports:

  • “8002:8080”

environment:

  • PENPOT_PUBLIC_URI=http://localhost:8080
  • PENPOT_DATABASE_URI=postgresql://postgres:penpot_secure_password@postgres:5432/penpot
  • PENPOT_REDIS_URI=redis://redis:6379/0 # 同じRedisを参照することでセッションが同期される
  • PENPOT_TELEMETRY_ENABLED=false

depends_on:

  • postgres
  • redis

networks:

  • penpot-net

volumes:
pgdata:
redisdata:

networks:
penpot-net:
driver: bridge

この設定のミソは、`penpot-frontend-1` と `penpot-frontend-2` の両方が、共通の `PENPOT_REDIS_URI` を向いている点です。これにより、ユーザーの認証状態やライブコラボレーションのイベントがRedis経由で同期され、裏側で何台サーバーが増えても、ユーザーからは「一つの滑らかな空間」として認識されます。

—

4. ロードバランサー配下での「WebSocket安定稼働」の極意

複数台のPenpotを立ち上げたら、その手前にロードバランサー(Nginx等)を置く必要があります。ここで多くのエンジニアがハマる罠が「WebSocketのコネクション断」です。

デザインツールでは、マウスカーソルの動きやオブジェクトの移動がミリ秒単位でWebSocketを通じて飛び交います。ロードバランサーがこれを適切にルーティング・維持してくれないと、「頻繁に接続が切れる」「カーソルがカクつく」といった最悪のUXを生み出します。

もし前段にNginxを配置する場合、以下の設定(特に`proxy_set_header Upgrade`周り)を必ず入れてください。

`nginx.conf` (ロードバランサー設定の抜粋)

upstream penpot_cluster {
# 負荷分散アルゴリズムとしてIPハッシュを推奨(同一ユーザーのセッションを同一コンテナに極力寄せつつ、冗長性を確保)
ip_hash;

server penpot-frontend-1:8080;
server penpot-frontend-2:8080;
}

server {
listen 80;
server_name design.yourcompany.local;

client_max_body_size 100M; # デザインデータや画像アップロードのために大きめに設定

location / {
proxy_pass http://penpot_cluster;

# 必須ヘッダーの設定
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# — WebSocketを安定稼働させるための魔法の呪文 —
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;

# タイムアウトを長めに設定(リアルタイム通信の切断を防ぐ)
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}

このNginx設定を入れることで、長時間のプロトタイピング作業中でもWebSocketが安定し、ストレスフリーな共同編集環境が完成します。

—

5. 動作確認:HelloWorldならぬ「同期テスト」の作法

環境が無事に立ち上がったら(`docker-compose up -d`)、正しくスケールアウトとRedisによるセッション共有が機能しているかテストしましょう。

1. ブラウザで `http://localhost:8080`(または設定したドメイン)にアクセスします。
2. アカウントを作成し、適当なチームと「HelloWorldプロジェクト」を作成します。
3. ここがポイント: ブラウザのシークレットウィンドウ(別セッション)で同じURLを開き、別のアカウント(または同じアカウント)でログインします。
4. ボード上に長方形(Rectangle)を配置し、ドラッグしてみてください。

もし、一方の画面での移動が、もう一方の画面にラグなくリアルタイムで反映されれば、Redisを介したWebSocketのPub/Subとセッション共有は大成功です!

さらにインフラのコンソールを開き、`docker-compose stop penpot-frontend-1` と叩いてあえてサーバー1台をブツ切りにしてみてください。ロードバランサーとRedisのおかげで、ユーザーのセッションがロストせず、もう一台のコンテナへシームレスに引き継がれる感動を味わえるはずです。

—

まとめ

今回は、Penpotのセルフホスト環境において、Redisを活用したセッション共有とスケールアウト構成の構築手順を解説しました。

  • Redisの導入により、複数サーバー間でのセッションとリアルタイム同期が完璧に担保される。
  • ロードバランサー(Nginx等)の適切なWebSocket設定により、巨大なデザインデータでもカクつかない強靭な通信環境が手に入る。

この構成さえ組んでしまえば、社内のセキュリティ基準をクリアしつつ、Figmaに負けない爆速で快適なデザイン・プロトタイピング基盤を自社のアカウント下に完全コントロールできます。

これをマスターすれば、あなたのインフラ・開発チームからの信頼は間違いなく爆上がりしますよ。ぜひ明日のインフラ構築に組み込んでみてください。それでは、良質なデザイン・開発ライフを!

タイトルとURLをコピーしました