Penpotマルチテナント型セルフホスト構築:Docker ComposeとNginx Proxy Managerで複数組織の環境を安全に分離する設計図
こんにちは。プロダクト開発の現場において、デザインシステムの一貫性と高速なプロトタイピングを両立させることは、常に最優先課題だ。特に受託開発や複数の独立したプロダクトラインを持つ組織において、デザインツールの環境分離は「セキュリティ」と「スケーラビリティ」の観点から避けて通れない。
オープンソースのFigmaキラーとして急成長を遂げているPenpotは、SVGをネイティブフォーマットとし、CSS GridやFlexboxの概念をそのままレイアウトに持ち込める点で、エンジニアとデザイナーの共通言語を作る最強のツールだ。
今回は、このPenpotをDocker ComposeとNginx Proxy Manager(NPM)を用いて完全分離されたマルチテナント環境として構築し、現場の生産性を極限まで引き上げるための実践的な設計図を伝授する。
—
1. なぜ複数組織・クライアントごとにPenpot環境を分けるべきか?
「一つのPenpotサーバーに全組織のチームを作ればいいのでは?」という疑問を持つかもしれない。しかし、プロダクトの規模が拡大するにつれて、単一インスタンス運用には致命的なボトルネックが生じる。
- データガバナンスとセキュリティの境界: クライアントAの未公開デザインデータが、クライアントBの目に触れるリスク(またはその逆)を物理的・論理的に排除する必要がある。
- リソースのアイソレーション: 特定のチームが重たい高解像度アセットを大量にアップロードしてCPU/メモリを圧迫した際、他のプロジェクトへ影響を与えてはならない。
- バージョンアップとメンテナンスの独立性: クライアントのリリーススケジュールに合わせて、特定の環境だけPenpotのバージョンアップを凍結・先行検証できる柔軟性が求められる。
これを実現するのが、コンテナベースのマルチテナント・アーキテクチャだ。
—
2. 開発スピードを劇的に高めるプロの知見(ショートカット・設定)
インフラの構築に入る前に、チーム全体の開発・デザインスピードを底上げするPenpotの核心に触れておこう。これらをチームの標準ルールとして強制することで、ツールの真価を発揮できる。
開発・デザインを加速する隠れたキーボードショートカット
- `Shift + R`: レスポンシブモードの切り替え(CSS Grid / Flexboxの挙動確認に必須)
- `Ctrl + Shift + C` (Mac: `Cmd + Shift + C`): 要素のCSSコードを瞬時にクリップボードへコピー
- `V`: コンポーネントのインスタンスからマスターコンポーネントへ一瞬でジャンプ
- `Alt + ドラッグ`: 正確なマージン・パディングの計測とスペーシングの調整
チーム開発におけるコンポーネント共有ルール
Penpotでは「ライブラリ」機能を用いてチーム間でコンポーネントを共有するが、マルチテナント環境では組織ごとに独立したライブラリサーバーとして機能するため、組織を跨いだ意図しないアセットの混入を防ぎつつ、組織内でのデザインアセットの属人化を防ぐことができる。
—
3. Docker Composeによるマルチテナント構成の具体的な設計
今回は、ベースとなるインフラストラクチャとして、Nginx Proxy Manager(NPM)をフロントに据え、各テナント(組織A, 組織B)ごとに独立したPenpotスタック(Web, Backend, PostgreSQL, Redis)をデプロイする構成をとる。
ディレクトリ構成案
/opt/penpot-multitenant/
├── proxy/ # Nginx Proxy Manager共通管理
│ └── docker-compose.yml
├── client-a/ # クライアントA専用環境
│ ├── docker-compose.yml
│ └── .env
└── client-b/ # クライアントB専用環境
├── docker-compose.yml
└── .env
実用的な設定ファイル:クライアントAの `docker-compose.yml`
以下の設定は、公式の推奨構成をベースにしつつ、コンテナ間のネットワーク分離とリソース制限(Resource Limits)を厳格に施したプロダクションレディなコードだ。
version: ‘3.8’
services:
penpot-frontend-a:
image: penpotapp/frontend:latest
restart: always
ports:
- “8001:8080” # NPMへルーティングするための内部ポート
networks:
- penpot-net-a
depends_on:
- penpot-backend-a
deploy:
resources:
limits:
cpus: ‘0.50’
memory: 512M
penpot-backend-a:
image: penpotapp/backend:latest
restart: always
networks:
- penpot-net-a
environment:
- PENPOT_FLAGS=disable-registration enable-telemetry=false
- PENPOT_DATABASE_URI=postgresql://penpot:secret_pass_a@penpot-db-a/penpot
- PENPOT_REDIS_URI=redis://penpot-redis-a:6379
- PENPOT_PUBLIC_URI=https://penpot-a.yourdomain.com
- PENPOT_SMTP_DEFAULT_FROM=noreply-a@yourdomain.com
- PENPOT_SMTP_HOST=smtp.sendgrid.net
- PENPOT_SMTP_PORT=587
- PENPOT_SMTP_USERNAME=apikey
- PENPOT_SMTP_PASSWORD=your_sendgrid_api_key
depends_on:
- penpot-db-a
- penpot-redis-a
deploy:
resources:
limits:
cpus: ‘1.0’
memory: 1536M
penpot-exporter-a:
image: penpotapp/exporter:latest
restart: always
networks:
- penpot-net-a
environment:
- PENPOT_PUBLIC_URI=http://penpot-backend-a:6060
- PENPOT_REDIS_URI=redis://penpot-redis-a:6379
deploy:
resources:
limits:
cpus: ‘0.5’
memory: 1024M
penpot-db-a:
image: postgres:15-alpine
restart: always
networks:
- penpot-net-a
volumes:
- penpot_db_data_a:/var/lib/postgresql/data
environment:
- POSTGRES_DB=penpot
- POSTGRES_USER=penpot
- POSTGRES_PASSWORD=secret_pass_a
deploy:
resources:
limits:
cpus: ‘1.0’
memory: 1024M
penpot-redis-a:
image: redis:7-alpine
restart: always
networks:
- penpot-net-a
deploy:
resources:
limits:
cpus: ‘0.25’
memory: 256M
volumes:
penpot_db_data_a:
name: penpot_db_data_a
networks:
penpot-net-a:
name: penpot-net-a
driver: bridge
—
4. SSL証明書の自動化とリソース制限によるサーバー安定稼働のコツ
マルチテナント環境において最も運用の手間がかかるのが「SSL証明書の管理」と「リソース枯渇による障害」だ。これをNginx Proxy ManagerとDockerの機能でスマートに解決する。
1. Nginx Proxy Manager (NPM) によるSSL自動化
各クライアント環境(例: `penpot-a.yourdomain.com`, `penpot-b.yourdomain.com`)を立ち上げたら、GUIベースのNPMで以下のようにプロキシホストを設定する。
1. Domain Names: `penpot-a.yourdomain.com`
2. Forward Scheme: `http`
3. Forward Hostname / IP: `<ホストのローカルIPまたはDockerブリッジIP>`(例: `172.17.0.1` もしくはコンテナ名)
4. Forward Port: `8001`(先ほどDocker Composeでマッピングしたポート)
5. SSL Tab: 「Request a new SSL Certificate」を選択し、Let’s Encryptの利用規約に同意。「Force SSL」を有効化。
これで、面倒なCertbotのCron設定や証明書更新の手間から完全に解放され、ワイルドカードや個別ドメインのSSLが完全自動化される。
2. リソース制限(Resource Limits)の徹底
先ほどの `docker-compose.yml` に含めた `deploy.resources.limits` は、マルチテナント運用において生命線となる。
一つのコンテナがメモリリークや重いエクスポート処理によってリソースを食いつぶし、同居している別のクライアント環境まで巻き込んでダウンする「noisy neighbor(騒がしい隣人)問題」を確実に防ぐ。
- Database (PostgreSQL): 1GB
- Backend (Clojure製コア): 1.5GB〜2GB
- Frontend / Redis: 軽量に抑える
サーバー全体の実搭載メモリに合わせてこれらの数値をチューニングし、監視ツール(cAdvisor + Prometheus + Grafanaなど)でリソース使用率を可視化しておくと完璧だ。
—
結びにかえて
Penpotのセルフホスト環境をマルチテナント化することは、単なるインフラの分割ではない。それは、「クライアントやプロジェクトごとの境界線をセキュアに引きつつ、開発者とデザイナーが最高速度でコラボレーションできる聖域を量産する仕組み」の構築に他ならない。
Docker Composeによる宣言的な環境構築と、Nginx Proxy Managerによるモダンなルーティングを組み合わせることで、運用の負荷を最小限に抑えながら、強固なプロトタイピング基盤を手に入れることができる。
さあ、今すぐコンテナを立ち上げ、次のプロジェクトのためのクリーンなデザイン空間をプロビショニングしよう。エンジニアリングの力で、デザインのワークフローを加速させるのだ。