PassIt 1.25.0 Docker Compose 部署指南
PassIt 1.25.0 三件套(应用+PostgreSQL 17+Valkey 8)Compose 部署全流程实测:镜像选型、迁移初始化、注册验证、持久化验证与五个排障实录。
PassIt 1.25.0 Docker Compose 部署指南
目标:在一台 Linux 服务器上用 Docker Compose 把 PassIt 1.25.0 完整跑起来——从拉镜像、编排 PostgreSQL/Valkey/应用三件套,到数据库迁移、注册首个账号、验证数据持久化。本文全部命令与输出均为 2026-10-24 实测回显。
部署形态速览:PassIt 是"单应用服务 + PostgreSQL + Valkey(Redis)"三件套,官方安装文档只写明 PostgreSQL 必需;本文实测发现 1.25.0 起 Valkey 也是必需组件(缺它应用日志持续报任务心跳失败,详见常见问题一节)。应用镜像内嵌 Angular 前端静态资源,无需独立前端服务。
一、环境信息
| 项目 | 值 | 备注 |
|---|---|---|
| 操作系统 | Ubuntu 22.04.4 LTS x86_64 | 长期支持版即可 |
| Docker | 29.8.1 | docker version 实测 |
| Docker Compose | v5.5.1 | docker compose version 实测 |
| 内存 / 磁盘 | 2C4G / 20GB | 官方托管版起始规格即 512MB/1vCPU,自托管留出余量 |
| 应用版本 | PassIt 1.25.0(2026-10-16 发布) | 官方前端仓库 tag 同日同步 |
| 数据库 | PostgreSQL 17(postgres:17 镜像) | 官方 compose.yml 指定版本 |
| 缓存 | Valkey 8(valkey/valkey:8 镜像) | 官方 compose.yml 同款选择 |
| 监听端口 | 8128(宿主)→ 8080(应用内) | 应用内固定 8080 |
| 部署目录 | /opt/passit/ | 本文操作基线目录 |
二、镜像选型说明
PassIt 官方发布渠道有三处,实测(查询日期 2026-10-24)对比后选 GitLab Registry 精确版本标签:
| 来源 | 标签 | 状态 | 结论 |
|---|---|---|---|
| registry.gitlab.com/passit/passit-frontend | 1.25.0 | 2026-10-16 构建,含前端静态资源与最新后端 | 推荐:与官方版本号一一对应,可回滚 |
| hub.docker.com/r/passit/passit | stable | 2026-04-10 更新(对应 1.24.0 时代) | 落后于最新版,仅适合"追官方默认"场景 |
| hub.docker.com/r/passit/passit | latest | 2019-01-11 后未更新 | 禁用:陈旧镜像 |
| registry.gitlab.com/passit/passit-frontend | main/master | 滚动开发版 | 不建议生产使用 |
补充实测数据:registry.gitlab.com/passit/passit-frontend:1.25.0 镜像约 523MB(amd64),内含 Python 3.14 运行时、Django 应用、granian 应用服务器与构建好的 Angular 前端;启动入口为镜像内 bin/start.sh(仅启动服务,不执行迁移)或 bin/migrate_and_start.sh(迁移后启动)。
三、前置条件
- 服务器已安装 Docker 与 Compose 插件,能访问镜像仓库;
- 已规划数据库口令与应用密钥(
SECRET_KEY,建议 40 位以上随机字符串); - 明确邮件验证通道:生产必须可发信(SMTP);本文为让"注册确认邮件"可被直接观测验证,采用控制台后端(邮件内容打到服务日志),配置方法见环境变量表;
- 若需公网访问,提前准备好域名解析与 TLS 证书(Let's Encrypt 即可);本篇以本机
http://localhost:8128验证为基线,生产 HTTPS 化的要求见《PassIt 安全加固指南》。
四、部署步骤
4.1 准备目录与编排文件
在 /opt/passit/ 下创建 docker-compose.yml:
name: passit-1.25.0-stack
services:
db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_DB: passit
POSTGRES_USER: passit
POSTGRES_PASSWORD: q1w2e3r4
volumes:
- ./pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U passit -d passit"]
interval: 5s
timeout: 5s
retries: 10
cache:
image: valkey/valkey:8
restart: unless-stopped
healthcheck:
test: ["CMD", "valkey-cli", "ping"]
interval: 5s
timeout: 5s
retries: 10
web:
image: registry.gitlab.com/passit/passit-frontend:1.25.0
restart: unless-stopped
command: bin/start.sh
ports:
- "8128:8080"
environment:
DATABASE_URL: postgres://passit:q1w2e3r4@db:5432/passit
CACHE_URL: redis://cache:6379/1
SECRET_KEY: "mK7vQ2xL9pR4nT8wZ3yF6jH1cB5dG0sA2eU7iO4qX9zN6mV3kJ8fW2rT5yU1hC4"
IS_DEBUG: "False"
SECURE_COOKIE: "False"
EMAIL_BACKEND: django.core.mail.backends.console.EmailBackend
DEFAULT_FROM_EMAIL: passit@example.com
EMAIL_CONFIRMATION_HOST: http://localhost:8128
DJANGO_LOG_LEVEL: INFO
depends_on:
db:
condition: service_healthy
cache:
condition: service_healthy
⚠️ 生产要点:
SECRET_KEY换成自己的随机值并保密;POSTGRES_PASSWORD与DATABASE_URL同步替换;公网 HTTPS 部署时删除SECURE_COOKIE: "False"(默认开启,需 HTTPS 配合);EMAIL_BACKEND与EMAIL_CONFIRMATION_HOST按邮件通道调整(SMTP 配置详见《PassIt 1.25.0 配置参数详解》)。
4.2 启动服务
root@passit-server:/opt/passit# docker compose up -d
[+] Running 5/5
✔ Network passit-1.25.0-stack_default Created
✔ Container passit-1.25.0-stack-db-1 Healthy
✔ Container passit-1.25.0-stack-cache-1 Healthy
✔ Container passit-1.25.0-stack-web-1 Started
确认运行状态:
root@passit-server:/opt/passit# docker compose ps
NAME IMAGE SERVICE CREATED STATUS PORTS
passit-1.25.0-stack-cache-1 valkey/valkey:8 cache 14 seconds ago Up 12 seconds (healthy) 6379/tcp
passit-1.25.0-stack-db-1 postgres:17 db 14 seconds ago Up 13 seconds (healthy) 5432/tcp
passit-1.25.0-stack-web-1 registry.gitlab.com/passit/passit-frontend:1.25.0 web 14 seconds ago Up 11 seconds 0.0.0.0:8128->8080/tcp, [::]:8128->8080/tcp
4.3 初始化数据库(每次升级后都要执行)
官方方式是启动后单独执行迁移:
root@passit-server:/opt/passit# docker compose run --rm web ./manage.py migrate
[+] Creating 1/0
✔ Container passit-1.25.0-stack-db-1 Running
Operations to perform:
Apply all migrations: account, admin, access, auth, cacheops, confirm_email, constance, contenttypes, django_vtasks, knox, ldap, mfa, organizations, secrets, sessions, sites
Running migrations:
No migrations to apply.
全新实例应显示逐条 Applying 记录;上面回显取自二次执行场景,No migrations to apply. 表示已迁移到位。另一种等价做法是把 web 服务启动命令改为镜像自带的 bin/migrate_and_start.sh(迁移完成后自动启动),适合希望"up 即完成一切"的编排习惯。
4.4 健康检查与首个账号注册
服务就绪后依次验证健康端点与账号可用性查询:
root@passit-server:/opt/passit# curl -s http://localhost:8128/api/_health/
ok
root@passit-server:/opt/passit# curl -s http://localhost:8128/api/ping/
{"ping":"pong"}
root@passit-server:/opt/passit# curl -s http://localhost:8128/api/username-available/admin@example.com/
{"available":true}
浏览器打开 http://localhost:8128/ 即见 Passit 登录页,注册入口为 /account/register。注册在客户端完成密钥生成(主密码不出浏览器),提交成功后服务端返回备份码;确认邮件(本文走控制台后端)直接看 web 服务日志:
Please confirm your email.
Your code is 4b005a.
Goto this link http://localhost:8128/account/confirm-email/022gvzQvj1R5cAWapwAHSKbiN7QxHM3XaA8vGYuhElBwMhdfdOYwZQ to confirm.
访问该链接完成邮箱确认(短码 4b005a 可在确认页面手工输入)。确认后登录、建组并存入第一条密码(浏览器操作为同名动作):
登录用户:admin@example.com
新建组:ops-team
新建密码:gitee-login(URL https://gitee.com,用户名 admin,密码 q1w2e3r4)
到数据库里验证"服务端只见密文"的零知识设计(只读检查,不改任何数据):
root@passit-server:/opt/passit# docker compose exec db psql -U passit -d passit -c "select name, data from secrets_secret where id = 1;"
name | data
-------------+-----------------------------------------------------
gitee-login | {"url": "https://gitee.com", "username": "admin"}
(1 行)
data 列只含非敏感字段(URL/用户名),密码字段存放在关联表的密文列中——这正是《PassIt 1.25.0 介绍与选型指南》所述零知识架构的落库形态。
4.5 升级
root@passit-server:/opt/passit# docker compose pull web
root@passit-server:/opt/passit# docker compose up -d
root@passit-server:/opt/passit# docker compose run --rm web ./manage.py migrate
要点:升级必须重跑迁移;先 pull 新版本号镜像再 up -d 重建;回滚需退回旧版本号镜像标签(数据迁移通常是向前单向的,跨版本回滚前先备份,见 4.6)。
4.6 备份与恢复
备份=数据库导出 + 编排目录:
root@passit-server:/opt/passit# docker compose exec db pg_dump -U passit -d passit > passit-$(date +%F).sql
root@passit-server:/opt/passit# tar czf passit-etc-$(date +%F).tar.gz docker-compose.yml pgdata/
恢复(实例重建到能 psql 的程度后):
root@passit-server:/opt/passit# cat passit-2026-10-24.sql | docker compose exec -T db psql -U passit -d passit
五、数据持久化说明
| 数据 | 位置 | 持久化方式 |
|---|---|---|
| 数据库 | ./pgdata:/var/lib/postgresql/data | 宿主目录 bind mount |
| 应用状态 | 无本地文件状态 | 全部状态在 PostgreSQL 与 Valkey 中 |
| 日志 | stdout | 由外部日志策略收集 |
实测验证(down 重建后数据原样保留):
root@passit-server:/opt/passit# docker compose down
[+] Running 5/4
✔ Container passit-1.25.0-stack-web-1 Removed
✔ Container passit-1.25.0-stack-cache-1 Removed
✔ Container passit-1.25.0-stack-db-1 Removed
✔ Network passit-1.25.0-stack_default Removed
root@passit-server:/opt/passit# docker compose up -d
[+] Running 4/4
✔ Network passit-1.25.0-stack_default Created
✔ Container passit-1.25.0-stack-db-1 Healthy
✔ Container passit-1.25.0-stack-cache-1 Healthy
✔ Container passit-1.25.0-stack-web-1 Started
重建后登录原账号、读取原有密码与组均正常(用户、组、密码三类数据完整存活),说明 bind mount 的 pgdata 承载了全部持久化状态。注意:docker compose down 不删 bind mount 数据,但 down -v 会连带删除匿名卷——本编排未使用匿名卷,仍建议不要随手加 -v。
六、环境变量表
web 服务(应用本体)全部变量见《PassIt 1.25.0 配置参数详解》,本编排实际使用的最小集合如下:
| 变量 | 示例值 | 作用 | 是否必需 |
|---|---|---|---|
| DATABASE_URL | postgres://passit:q1w2e3r4@db:5432/passit | 数据库连接串 | 必需 |
| CACHE_URL | redis://cache:6379/1 | 缓存/任务队列(Valkey)连接 | 1.25.0 必需 |
| SECRET_KEY | 40+ 位随机串 | 会话与 Token 签名密钥 | 生产必需(缺省启动即失败) |
| IS_DEBUG | False | 生产必须关闭调试 | 建议显式设置 |
| SECURE_COOKIE | False | HTTP 本机验证用;生产 HTTPS 删除此行走默认 True | 视场景 |
| EMAIL_BACKEND | django.core.mail.backends.console.EmailBackend | 邮件后端;SMTP 部署用默认 smtp 后端并配 EMAIL_URL | 视场景 |
| DEFAULT_FROM_EMAIL | passit@example.com | 发件人地址 | 必需 |
| EMAIL_CONFIRMATION_HOST | http://localhost:8128 | 确认邮件中的回链主机 | 必需 |
| DJANGO_LOG_LEVEL | INFO | 日志级别 | 可选 |
db 服务(postgres:17):POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORD 三件套,与 DATABASE_URL 保持一致。
七、配置参数说明
- CACHE_URL 为什么必须:1.25.0 后端默认把缓存与后台任务队列指向 Valkey(django_vcache / django_vtasks),不配 Valkey 时服务能起、页面能开,但后台任务(如发确认邮件)会反复报连接失败——见常见问题 11.1;
- EMAIL_CONFIRMATION_HOST 决定确认链接:邮件里的"点击确认"链接由它拼接,必须写用户浏览器可达的地址(公网域名或本机端口),配错会导致确认链接打不开;
- SECRET_KEY 的代价:更换会导致既有登录 Token/会话失效(用户需重新登录,数据无损),因此一旦定下就不要随意换;
- SECURE_COOKIE 与 HTTP:默认 True 会给会话 Cookie 加 Secure 标记,纯 HTTP 访问时浏览器拒收、登录形同虚设;本机 HTTP 验证必须显式 False,生产 HTTPS 保持默认 True;
- EMAIL_BACKEND 与 EMAIL_URL 的关系:
EMAIL_URL是django-environ 风格的连接串;实测 1.25.0 中想让邮件走控制台,仅设EMAIL_URL=consolemail://不生效,必须同时显式EMAIL_BACKEND(见常见问题 11.2)。
八、配置文件挂载
PassIt 无配置文件,全部配置经环境变量注入(settings.py 读取);本编排仅有数据库目录一处挂载(./pgdata)。若要外置 TLS 终端(nginx/caddy),其配置文件在宿主机另行管理,不在本编排内。
九、等价 docker run
不使用编排时的等价启动命令(三步,注意先后依赖):
# 1. 数据库
docker run -d --name passit-db \
-e POSTGRES_DB=passit -e POSTGRES_USER=passit -e POSTGRES_PASSWORD=q1w2e3r4 \
-v /opt/passit/pgdata:/var/lib/postgresql/data \
--restart unless-stopped postgres:17
# 2. 缓存
docker run -d --name passit-cache \
--restart unless-stopped valkey/valkey:8
# 3. 应用(与上两个同处一个自定义网络,或改用 IP/宿主网络寻址)
docker run -d --name passit-web \
-p 8128:8080 --restart unless-stopped \
-e DATABASE_URL=postgres://passit:q1w2e3r4@passit-db:5432/passit \
-e CACHE_URL=redis://passit-cache:6379/1 \
-e SECRET_KEY=mK7vQ2xL9pR4nT8wZ3yF6jH1cB5dG0sA2eU7iO4qX9zN6mV3kJ8fW2rT5yU1hC4 \
-e IS_DEBUG=False -e SECURE_COOKIE=False \
-e EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend \
-e DEFAULT_FROM_EMAIL=passit@example.com \
-e EMAIL_CONFIRMATION_HOST=http://localhost:8128 \
registry.gitlab.com/passit/passit-frontend:1.25.0 bin/start.sh
docker exec passit-web ./manage.py migrate
生产仍建议编排方式:健康检查依赖、依赖启动顺序与重建一致性由编排保证。
十、常用运维命令
| 操作 | 命令 |
|---|---|
| 查看服务状态 | docker compose ps |
| 跟踪应用日志 | docker compose logs -f web |
| 执行迁移 | docker compose run --rm web ./manage.py migrate |
| 进入应用运维壳 | docker compose exec web bash |
| 数据库直连 | docker compose exec db psql -U passit -d passit |
| 重建单服务 | docker compose up -d --force-recreate web |
| 完整停栈 | docker compose down |
| 整栈备份 | 见 4.6 节两条命令 |
十一、常见问题(排障实录)
11.1 缺少 Valkey:任务心跳持续报错
现象:服务能启动、页面能打开,但日志反复出现:
[WARNING] Task heartbeat missed: Failed initial liveness heartbeat.
ConnectionError: Connection failed: timed out.
根因:只按官方安装文档起了"应用 + PostgreSQL",没有 Valkey。1.25.0 的缓存与后台任务队列默认指向 redis://redis:6379/1,连不上即报错,确认邮件等异步任务也会失败。处置:编排中补 valkey/valkey:8 服务并设置 CACHE_URL=redis://cache:6379/1(见 4.1),重启后日志恢复干净。
11.2 consolemail:// 不生效:确认邮件发送失败
现象:注册后日志报:
SMTPServerDisconnected: Connection unexpectedly closed
根因:设置了 EMAIL_URL=consolemail://,期望邮件打到控制台,但 1.25.0 的设置读取顺序导致该值未覆盖邮件后端,实际仍用默认 SMTP 后端去连邮件服务器。处置:显式设置 EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend(验证场景);生产走 SMTP 时保持默认后端并正确配置 EMAIL_URL(如 smtp+tls://user@smtp.example.com:587)。
11.3 HTTP 下登录不生效(Cookie 被拒收)
现象:HTTPS 未就绪时本机验证,登录请求返回成功但页面仍处于未登录状态。根因:SECURE_COOKIE 默认 True,会话 Cookie 带 Secure 标记,纯 HTTP 浏览器拒收。处置:本机 HTTP 验证设 SECURE_COOKIE=False;生产必须上 HTTPS 并删除该变量。
11.4 注册提交 400:public_key / private_key / client_salt 必填
现象:直接调 POST /api/users/ 只带邮箱密码,返回:
400 {"public_key": ["This field is required."], "private_key": ["This field is required."], "client_salt": ["This field is required."]}
这不是故障,而是零知识设计的必然:加密材料(公钥/加密私钥/盐值)只能由客户端在浏览器里生成,服务端不会代办。用正常 Web 注册流程即可,不要用脚本裸调该端点。
11.5 端口被占用
现象:up -d 报 Bind for 0.0.0.0:8128 failed: port is already allocated。处置:改宿主侧端口映射(如 8129:8080),应用内 8080 固定不变;同时检查 EMAIL_CONFIRMATION_HOST 是否需要同步更新端口。
十二、参考链接
- 官方安装指南:https://passit.io/install/ (查询日期 2026-10-24)
- 官方生产编排参考:https://gitlab.com/passit/passit-frontend/-/blob/master/docker-compose.production.yml
- 应用镜像(GitLab Registry,1.25.0):https://gitlab.com/passit/passit-frontend/container_registry
- 后端启动脚本 bin/start.sh:https://gitlab.com/passit/passit-backend/-/blob/master/bin/start.sh
- 升级指南:https://passit.io/update/
- 本平台系列篇:《PassIt 1.25.0 介绍与选型指南》、《PassIt 1.25.0 配置参数详解》、《PassIt 安全加固指南》
- 本平台同类部署篇:《Passbolt 5.16.0 Docker Compose 部署指南》、《Vaultwarden 1.37.4 Docker Compose 部署指南》