Penpot
PVE 配置
| 配置 | 建议值 |
|---|---|
| 系统 | Debian 12/13 或 Ubuntu 24.04 LTS |
| CPU | 4 vCPU,类型选择 host |
| 内存 | 8GB 固定内存 |
| 系统盘 | 100GB,VirtIO SCSI、开启 Discard |
| 网卡 | VirtIO,配置固定局域网 IP |
| QEMU Agent | 开启 |
| GPU | 不需要直通 |
部署
sudo mkdir -p /opt/penpot
sudo chown "$USER":"$USER" /opt/penpot
cd /opt/penpot
curl -fsSLo docker-compose.yaml \
https://raw.githubusercontent.com/penpot/penpot/main/docker/images/docker-compose.yaml生成密钥:
sh
python3 -c "import secrets; print(secrets.token_urlsafe(64))"
python3 -c "import secrets; print(secrets.token_urlsafe(32))"vim .env
sh
# 固定版本,升级时手动修改并检查发行说明。
PENPOT_VERSION=2.16
# 用户访问地址,必须和 Traefik 域名一致。
PENPOT_PUBLIC_URI=https://ui.lab.q123q.cc
# Penpot VM 的内网 IP。
PENPOT_LISTEN_IP=10.0.0.150
# 使用随机值替换。
PENPOT_SECRET_KEY=mgwadG--NXT4MRjE09CxuOLI6Xl22vcz5xMZpm-hJwhnboOxxUIR5GiBzkMbOGPQ3Z44rW4hb0P0WDcfZtZTQw
PENPOT_DATABASE_PASSWORD=_ssyPfi0IIgwSCRxpEq7wkTrAgezsIEP-ERBNTuyVrEvim docker-compose.yml
yml
name: penpot
# ============================================================
# Penpot 公共配置
# ============================================================
x-penpot-common-env: &penpot-common-env
# 【重点】必须是用户最终访问的 HTTPS 地址。
# 登录回调、资源地址、邀请链接都会依赖它。
PENPOT_PUBLIC_URI: "${PENPOT_PUBLIC_URI:?PENPOT_PUBLIC_URI is required}"
# 【重点】
# disable-email-verification:
# 当前没有真实 SMTP,因此关闭邮箱验证。
#
# enable-log-emails / enable-log-invitation-tokens:
# 邮件和邀请链接输出到 backend 日志。
#
# enable-prepl-server:
# 允许通过 manage.py 创建和管理用户。
#
# enable-mcp:
# 启用 Penpot MCP。
#
# HTTPS 环境不要添加 disable-secure-session-cookies。
PENPOT_FLAGS: >-
disable-email-verification
enable-log-emails
enable-log-invitation-tokens
enable-prepl-server
enable-mcp
# 最大上传请求约 350 MiB。
# 已删除废弃的 PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE。
PENPOT_HTTP_SERVER_MAX_BODY_SIZE: "367001600"
x-penpot-secret-env: &penpot-secret-env
# 【重点】必须保持不变,否则重启后会导致会话、邀请链接等失效。
PENPOT_SECRET_KEY: "${PENPOT_SECRET_KEY:?PENPOT_SECRET_KEY is required}"
services:
# ==========================================================
# 对外入口
# 外部 Traefik 将请求转发到该服务的 9001 端口。
# ==========================================================
penpot-frontend:
image: "penpotapp/frontend:${PENPOT_VERSION:-2.16}"
restart: unless-stopped
ports:
# 【重点】建议绑定到 Penpot VM 的内网 IP。
# 另外应在防火墙中仅允许 Traefik 主机访问 9001。
- "${PENPOT_LISTEN_IP:-0.0.0.0}:9001:8080"
volumes:
- penpot_assets:/opt/data/assets
depends_on:
- penpot-backend
- penpot-exporter
- penpot-mcp
environment:
<<: *penpot-common-env
networks:
- penpot
# ==========================================================
# Penpot 后端
# ==========================================================
penpot-backend:
image: "penpotapp/backend:${PENPOT_VERSION:-2.16}"
restart: unless-stopped
volumes:
# 【重点】用户上传的图片、字体和其他资源存放于此。
- penpot_assets:/opt/data/assets
depends_on:
penpot-postgres:
condition: service_healthy
penpot-valkey:
condition: service_healthy
environment:
<<: [*penpot-common-env, *penpot-secret-env]
# PostgreSQL
PENPOT_DATABASE_URI: postgresql://penpot-postgres/penpot
PENPOT_DATABASE_USERNAME: penpot
PENPOT_DATABASE_PASSWORD: "${PENPOT_DATABASE_PASSWORD:?PENPOT_DATABASE_PASSWORD is required}"
# Valkey 用于 WebSocket 通知和内部协调。
PENPOT_REDIS_URI: redis://penpot-valkey/0
# 使用 Docker Volume 保存上传资源。
PENPOT_OBJECTS_STORAGE_BACKEND: fs
PENPOT_OBJECTS_STORAGE_FS_DIRECTORY: /opt/data/assets
networks:
- penpot
# ==========================================================
# Penpot MCP
# 需要保留 enable-mcp,并且当前只能运行单实例 Penpot。
# ==========================================================
penpot-mcp:
image: "penpotapp/mcp:${PENPOT_VERSION:-2.16}"
restart: unless-stopped
networks:
- penpot
# ==========================================================
# 文件导出服务
# 用于 PNG、SVG、PDF 等导出,不能删除。
# ==========================================================
penpot-exporter:
image: "penpotapp/exporter:${PENPOT_VERSION:-2.16}"
restart: unless-stopped
depends_on:
penpot-valkey:
condition: service_healthy
environment:
<<: *penpot-secret-env
PENPOT_PUBLIC_URI: "${PENPOT_PUBLIC_URI:?PENPOT_PUBLIC_URI is required}"
# 【重点】这是容器内部地址,不要改成公网域名。
PENPOT_INTERNAL_URI: http://penpot-frontend:8080
PENPOT_REDIS_URI: redis://penpot-valkey/0
networks:
- penpot
# ==========================================================
# PostgreSQL
# ==========================================================
penpot-postgres:
image: postgres:15
restart: unless-stopped
stop_signal: SIGINT
healthcheck:
test: ["CMD-SHELL", "pg_isready -U penpot -d penpot"]
interval: 5s
timeout: 5s
retries: 10
start_period: 10s
environment:
POSTGRES_INITDB_ARGS: --data-checksums
POSTGRES_DB: penpot
POSTGRES_USER: penpot
POSTGRES_PASSWORD: "${PENPOT_DATABASE_PASSWORD:?PENPOT_DATABASE_PASSWORD is required}"
volumes:
# 【重点】这是最重要的备份对象之一。
- penpot_postgres_v15:/var/lib/postgresql/data
networks:
- penpot
# ==========================================================
# Valkey
# 临时状态和 WebSocket 协调服务,不需要额外持久化。
# ==========================================================
penpot-valkey:
image: valkey/valkey:8.1
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "valkey-cli ping | grep PONG"]
interval: 3s
timeout: 3s
retries: 10
start_period: 5s
environment:
VALKEY_EXTRA_FLAGS: >-
--maxmemory 128mb
--maxmemory-policy volatile-lfu
networks:
- penpot
networks:
penpot:
name: penpot_internal
volumes:
# 显式指定名称,避免修改 Compose 目录名后创建一套新的空卷。
penpot_postgres_v15:
name: penpot_postgres_v15
penpot_assets:
name: penpot_assets