【オンプレ構築】PenpotをDockerで動かしてみた Figma風UIデザイン環境の代替ツールとして最適

はじめに

PenpotはFigma風のUIデザインツールで、オープンソースとして提供されています。
Reactで画面を実装する前にレイアウトを固めておきたかったため、今回はPenpotを自宅サーバーにDockerで構築してみました。
オンプレ環境で完結するUIデザインツールが欲しい方の参考になればうれしいです。

目次

Penpotをオンプレ構築しようと思った理由

UIレイアウトを作る環境を自宅サーバーで完結させたかった

Reactで実際に画面を組み立てる前に、まずレイアウトだけを視覚的に固めておきたい場面があります。しかし、Figmaのようなクラウドサービスは外部依存が大きく、データを自分の環境に保管しておきたいときにやや使いづらい側面があります。

開発環境をすべて自分のコントロール下に置けるという点も、オンプレでUIデザイン環境を整えたかった理由のひとつです。

Penpotを選んだ理由は様々

  • Figmaと似た操作性でレイアウトを作れる
  • オープンソースなので自宅サーバー上で動かせる
  • Dockerで構築できるため環境を壊しても簡単に立て直せる
  • React実装時のデザイン迷いを減らせる

特に、「オンプレでUIデザインが完結する」という点は、開発環境を自宅に集約したい人には大きなメリットです。
これらの理由から、まずはDockerでPenpotを構築してみることにしました。

今回の構成と前提条件

Penpot公式の推奨構成に従い、動作の安定性が高い、オンプレ用途として最低限でありつつ十分実用的な構成を狙った環境を構築します。

サーバー環境

今回、Penpotを構築したサーバー環境は次のとおりです。

  • OS:Ubuntu 22.04 LTS
  • CPU/メモリ:一般的な自宅サーバー用途(特別なスペックは不要)
  • ローカルネットワーク内でアクセス(オンプレ環境)
  • インターネット接続:Dockerイメージ取得のため外部へ通信できること

Penpotはコンテナとして動作するため、サーバーに高い性能は求められず、Dockerが動く環境であればほとんど問題ありません。

インストール済みソフトウェア

事前に、以下のソフトウェアがインストールされていることを前提としています。

  • Docker
  • Docker Compose

特に、Composeが使えると複数コンテナ(PostgreSQL / Redis / Penpot本体)をまとめて扱えるため、構築が楽になります。

Dockerのインストール方法は以下の記事をご覧ください。合わせて、docker-composeも使えるようになります。

Dockerで立ち上げるサービス構成

今回の最小構成では、Penpotを次の4サービスで動かします。

  • penpot-frontend(UI部分)
  • penpot-backend(メイン処理)
  • postgres(データベース)
  • redis(キュー処理)

PenpotをDockerで構築する手順

ここからは、実際にPenpotをDockerで立ち上げる手順を紹介します。
手順はシンプルで、作業用フォルダを準備して docker-compose.yml を配置し、コンテナを起動するだけです。Docker環境さえ整っていれば、数分でPenpotを動かすことができます。

作業用ディレクトリを作成する

まずは、Penpotの構築に使用するディレクトリを作成します。

mkdir penpot-docker
cd penpot-docker

このフォルダに docker-compose.yml を置き、データ永続化のボリュームもここから管理します。

docker-compose.yml を作成する

ここでは、Penpot公式の docker-compose をベースにしつつ、オンプレ環境で使いやすい最小構成に絞った docker-compose.yml を作成します。

最小構成とは、オンプレ環境でPenpot が動作することを目標にした、必要な 4 つのサービス(frontend / backend / postgres / valkey)だけを使い、Traefik や MinIO を省いた構成です。

Penpotの公式 docker-compose.yml
version: "3.8"

networks:
  penpot:

volumes:
  penpot_postgres_v15:
  penpot_assets:

services:
  penpot-frontend:
    image: "penpotapp/frontend:2.11.1"
    restart: unless-stopped
    ports:
      - "9001:8080"
    volumes:
      - penpot_assets:/opt/data/assets
    depends_on:
      - penpot-backend
      - penpot-exporter
    networks:
      - penpot
    environment:
      PENPOT_FLAGS: "disable-email-verification enable-smtp disable-secure-session-cookies"
      PENPOT_HTTP_SERVER_MAX_BODY_SIZE: 31457280
      PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE: 367001600

  penpot-backend:
    image: "penpotapp/backend:2.11.1"
    restart: unless-stopped
    volumes:
      - penpot_assets:/opt/data/assets
    depends_on:
      penpot-postgres:
        condition: service_healthy
      penpot-valkey:
        condition: service_healthy
    networks:
      - penpot
    environment:
      PENPOT_PUBLIC_URI: "http://サーバーのIPアドレスまたはホスト名:9001"
      PENPOT_DATABASE_URI: "postgresql://penpot-postgres/penpot"
      PENPOT_DATABASE_USERNAME: "penpot"
      PENPOT_DATABASE_PASSWORD: "penpot"
      PENPOT_REDIS_URI: "redis://penpot-valkey/0"
      PENPOT_ASSETS_STORAGE_BACKEND: "assets-fs"
      PENPOT_STORAGE_ASSETS_FS_DIRECTORY: "/opt/data/assets"
      PENPOT_TELEMETRY_ENABLED: "true"
      PENPOT_TELEMETRY_REFERER: "compose"
      PENPOT_SECRET_KEY: "change-this-insecure-key"
      PENPOT_FLAGS: "disable-email-verification"

  penpot-exporter:
    image: "penpotapp/exporter:2.11.1"
    restart: unless-stopped
    depends_on:
      penpot-valkey:
        condition: service_healthy
    networks:
      - penpot
    environment:
      PENPOT_SECRET_KEY: "change-this-insecure-key"
      PENPOT_PUBLIC_URI: "http://penpot-frontend:8080"
      PENPOT_REDIS_URI: "redis://penpot-valkey/0"

  penpot-postgres:
    image: "postgres:15"
    restart: unless-stopped
    stop_signal: SIGINT
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U penpot"]
      interval: 2s
      timeout: 10s
      retries: 5
      start_period: 2s
    volumes:
      - penpot_postgres_v15:/var/lib/postgresql/data
    networks:
      - penpot
    environment:
      - POSTGRES_INITDB_ARGS=--data-checksums
      - POSTGRES_DB=penpot
      - POSTGRES_USER=penpot
      - POSTGRES_PASSWORD=penpot

  penpot-valkey:
    image: "valkey/valkey:8.1"
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "valkey-cli ping | grep PONG"]
      interval: 1s
      timeout: 3s
      retries: 5
      start_period: 3s
    networks:
      - penpot
    environment:
      - VALKEY_EXTRA_FLAGS=--maxmemory 128mb --maxmemory-policy volatile-lfu

  penpot-mailcatch:
    image: "sj26/mailcatcher:latest"
    restart: unless-stopped
    expose:
      - "1025"
    ports:
      - "1080:1080"
    networks:
      - penpot

※ PENPOT_PUBLIC_URI の値は、ご自身の環境に合わせて書き換えてください。↓の部分です
 ”http://サーバーのIPアドレスまたはホスト名:9001″

この構成のポイント

  • 執筆時点では Penpot 本体の安定版を 2.11.1 として固定している(frontend / backend / exporter は同じバージョンを指定)
  • データベースは公式と同じく PostgreSQL 15 を利用している
  • キャッシュ兼通知には、公式が Redis の代わりに採用している Valkey 8.1(valkey/valkey:8.1 を使用している
  • PENPOT_REDIS_URI の値は redis://penpot-valkey/0 のままだが、これは Valkey が Redis 互換で動作するためで、公式 compose と同じ指定
  • PENPOT_PUBLIC_URI はあとでブラウザからアクセスするときの URL に合わせて、自分のサーバーの IP アドレスやホスト名に書き換える
  • PENPOT_SECRET_KEY はサンプル値のままだとセキュリティ的に弱いため、本番運用する場合はランダムな文字列に置き換える
  • PENPOT_FLAGS=disable-email-verification を指定して メールアドレスの確認機能を無効化

この構成の公式との差分とバージョンの注意点

Traefik や MinIO は省いてます。公式リポジトリの docker-compose には、Traefik や MinIOの記載がありますが、これは、外部公開向けのサービスです。今回は、オンプレ上で動作させる最小構成で組むことが目的であるため、Traefik や MinIO は省いた構成になっています。

最新の情報は公式の Release や docker-compose を確認して、合わせるようにしてください。

Penpotの公式 docker-compose.yml

なお、Penpot 本体の最新バージョン番号は docker-compose.yml には明記されていないため、
最新版を確認する場合は公式の Release ページをご覧ください。

Penpotの公式Release

コンテナを起動する

以下のコマンドでコンテナをバックグラウンド起動します。

docker compose up -d

初回はイメージのダウンロードが入るため、数十秒ほどかかります。

状態を確認する

起動後、各コンテナの状態を確認します。

docker compose ps

すべてのサービスが running になっていればOKです。以下のサービス名を確認してください。

  • penpot-frontend
  • penpot-backend
  • penpot-postgres
  • penpot-redis

どれかが exit になっている場合はログを確認してみてください。

docker logs penpot-backend

※ penpot-backend サービスがexit時の例です

(任意)サーバー再起動時も自動起動させたい場合

自宅サーバーで運用する場合、再起動後に自動起動にすると便利です。
その場合、Compose ファイルの各サービスに以下の例を参考に追加します。

penpot-backend:
  image: penpotapp/penpot-backend:latest
  restart: unless-stopped

ブラウザからアクセスして初期設定する

コンテナの起動ができたら、次はブラウザからPenpotにアクセスして初期設定を行います。ここでは、管理者ユーザーの作成と、ログインできるところまでを確認します。

初回アクセス用のURLを開く

まずはクライアントPCのブラウザから、PenpotのURLを開きます。

http://サーバーのIPアドレス:9001

docker-compose.yml9001:80 を指定しているため、ブラウザからはポート9001でアクセスします。

ドメイン経由でアクセスしたい場合は、Nginx や Apache にリバースプロキシ設定が必要です(本記事では割愛)
まずは http://サーバーIP:9001 で動作確認してください

以下の画面が出れば成功です。

もしこの時点でページが開かない場合は、次の点を確認します。

  • サーバーのIPアドレスが正しいか
  • docker compose pspenpot-frontendrunning になっているか
  • ファイアウォールでポート9001がブロックされていないか

管理者ユーザーを作成する

初回アクセス時は、Penpotのセットアップ画面が表示されます。
ここで、最初のユーザー(=管理者)を作成します。

ログインボタンのすぐ下の、Create an accountをクリックしてユーザー登録します。

入力する内容の例は次のとおりです。

  • 名前
  • メールアドレス
  • パスワード

このユーザーがPenpot全体を管理するアカウントになるので、忘れないメールアドレスとパスワードを設定しておきます。今回はメール認証をしない構成にしていますので、メールチェックすることなくユーザー作成が出来ていると思います。

初回セットアップ

Penpot では初回ログイン時に 3ステップの簡単なセットアップ画面が表示されます。
この画面の内容は Penpot のバージョンによって異なるそうですが、アンケートの様なもので機能に影響はありません。

日本語フォントを設定する

まずは日本語の設定をしましょう。画面左したのユーザー名をクリックすると表示されるYour accountをクリック。SettingsタグからLANGUAGEを日本語に変更します。※ 部分的にしか日本語化されませんでした・・・

使ってみた感想

思ったより難しかった【最初の壁はここ】

いざ自分でゼロから画面を作ってみようとすると、「背景を置く」「文字を書く」くらいは何とかできても、そこから UI として形にするのが思ったより難しいことに気づきました。

なんだこれは?と思われるかもしれませんが、今回試しに触ってみたのがこちらです。

背景画像を敷いて、タイトルを置いて、右側にメニューの枠を作ってみたのですが、バランスが難しく、UIデザインの奥深さを痛感しました。

まずはライブラリを使うのが正解【UI設計の基礎が分かる】

ライブラリからダウンロードして取り込んでみたのがこちらです。

分かったことは、左側のツリーを見ると段落のようになっていることが分かります。ブロックをいくつか作成し、その中に更にパーツを作っていくように作成されています。こういったライブラリを参考に使い方を学ぶのが正解と感じました。

まとめ:Penpotはオンプレでも手軽に動く、使い方には慣れが必要

今回、Linux を入れたミニPC上に Penpot を Docker で構築し、クライアント側は Windows からアクセスしてみましたが、動作は非常に軽快でした。
オンプレミス環境でも問題なく使えることを実感できました。

一方で、実際にUIをゼロから作ろうとすると、背景を置いたり文字を書く程度なら簡単でも、UIとして形にするには慣れが必要で、デザインの奥深さも感じました。

ただし、Penpot には便利なライブラリが多数用意されており、プロが作ったUI構造を参考にしながら学べるため、最初の習得にはライブラリを活用するのが正解だと感じました。

オンプレで UI デザイン環境を構築したい方には、Penpot は「軽快に動く × 自由度が高い」おすすめの選択肢です。

  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次