Cleep 0.4.4 Docker Compose 部署指南
Ubuntu 24.04 + Docker Compose 从零部署 Cleep 0.4.4 实测指南:GHCR 镜像与 PostgreSQL 16 双服务编排、管理员账号引导、数据持久化布局、备份脚本初验、等价 docker run 与常见问题排障。
Cleep 0.4.4 Docker Compose 部署指南
目标:在 Ubuntu 24.04 服务器上用 Docker Compose 从零部署 Cleep 0.4.4(官方
ghcr.io/blindpassasjer/cleep镜像 + PostgreSQL 16),覆盖环境变量准备、首个管理员账号引导、启动验证、数据持久化布局、备份脚本初验与常用运维命令。文中全部命令与回显均在真实部署环境(Ubuntu 24.04、Docker Compose v2、Cleep 0.4.4 镜像 digestsha256:60da6a78…、PostgreSQL 16.15)实测通过。Cleep 的定位与选型对比见本专栏《Cleep 0.4.4 介绍与选型指南》。
一、环境信息
本篇部署目标与实测环境的关键信息如下,读者按本文操作时请将 IP 与密码换成自己服务器的取值:
- 操作系统:Ubuntu 24.04 LTS,x86_64
- 容器运行时:Docker(支持 Compose v2 插件,
docker compose子命令可用) - 应用镜像:
ghcr.io/blindpassasjer/cleep:latest(2026-10-25 实查 digestsha256:60da6a78444ed38f2b4074c35a1a208b368c1b3aa75f3fe0c1f1971eefa98faf,镜像 OCI labelorg.opencontainers.image.version=0.4.4,大小约 365MB) - 数据库镜像:
postgres:16-alpine(实测解析为 PostgreSQL 16.15) - 服务端口:Cleep 服务在 6169 端口监听,本文对外发布 8140 端口(可按需改)
- 部署目录:
/opt/cleep/(compose 文件与.env所在),数据目录/opt/cleep/data/postgres/与/opt/cleep/data/attachments/,备份目录/opt/cleep/backups/ - 演示管理员账号:
admin@quzuo.net/q1w2e3r4(由.env的ADMIN_EMAIL/ADMIN_PASSWORD首次启动引导创建)
二、镜像选型说明
Cleep 只提供一种官方发行形态——GHCR 上的容器镜像 ghcr.io/blindpassasjer/cleep,配合仓库自带的 docker-compose.yml 一键起「应用 + PostgreSQL」双服务。没有 deb/rpm 等系统包,也不建议手工 npm 部署(那是开发形态)。
镜像标签策略(2026-10-25 实查 GHCR tags 接口):
| 标签形态 | 示例 | 说明 | 用途建议 |
|---|---|---|---|
latest | ghcr.io/blindpassasjer/cleep:latest | 跟随 main 分支每次推送自动构建 | 个人/NAS 快速上手(本文实测采用,当前即 0.4.4) |
sha-<commit> | ghcr.io/blindpassasjer/cleep:sha-cd81a01 | 每个提交一个不可变标签 | 需要精确回滚到某提交时使用 |
| digest 锁定 | @sha256:60da6a78… | 内容寻址、绝对不可变 | 生产环境推荐,升级由运维显式改 digest 触发 |
⚠️ 注意:GHCR 上没有
0.4.4这类版本号标签(2026-10-25 实查仅有latest与 90 余个sha-*标签);latest会随每次提交漂移,生产环境请改用 digest 锁定。
如何选:家庭 NAS / 个人使用直接跟 latest 即可(升级 = docker compose pull && docker compose up -d);对稳定性有要求的环境用 ghcr.io/blindpassasjer/cleep@sha256:60da6a78444ed38f2b4074c35a1a208b368c1b3aa75f3fe0c1f1971eefa98faf 形式锁定本文实测的 0.4.4 构建。
三、前置条件
- 已安装 Docker 与 Compose v2 插件,以下命令能正常输出版本号:
docker --version && docker compose version
-
服务器可访问 GHCR(
ghcr.io)。国内网络拉取慢或超时时,为 Docker 守护进程配置代理后重试docker compose pull;本文实测经代理拉取成功。 -
规划一个空闲的对外 Web 端口,本文用 8140,执行前先确认未占用:
ss -ltn | grep ':8140\b' || echo "8140 空闲"
实测回显(端口空闲时):
8140 空闲
- 创建部署目录与数据目录。Cleep 的 Postgres 服务以 uid/gid 999 运行(镜像内置 postgres 用户),数据目录必须先把属主改成 999,否则数据库首次初始化会因权限失败:
mkdir -p /opt/cleep/data/postgres /opt/cleep/data/attachments /opt/cleep/backups
chown -R 999:999 /opt/cleep/data/postgres
命令无回显即为成功;ls /opt/cleep/data/ 应看到 attachments postgres 两个目录。
四、部署步骤
本节按「准备环境变量 → 编写编排文件 → 拉取镜像 → 启动 → 验证」的顺序完成从零到可用。Cleep 官方推荐即为此形态,无需其他任何依赖。
4.1 准备环境变量文件
Cleep 的全部运行时配置通过环境变量注入,compose 项目目录下的 .env 文件负责承载。先生成会话签名密钥(64 位十六进制随机串):
openssl rand -hex 32
实测回显(每次生成不同,请使用你自己生成的值):
784e82cbbf04d24479a87fb9263bd51b836e8db2f09ddde4701dd0eeebfdd001
创建 /opt/cleep/.env,内容如下(密码等敏感值按自己环境替换;本文演示值可直接用于测试):
# /opt/cleep/.env
PUID=999
PGID=999
POSTGRES_PASSWORD=cleepdb2026
DATABASE_URL=postgres://cleep:cleepdb2026@postgres:5432/cleep
SESSION_SECRET=784e82cbbf04d24479a87fb9263bd51b836e8db2f09ddde4701dd0eeebfdd001
PORT=6169
COOKIE_SECURE=false
TRUST_PROXY=false
AUTH_RATE_LIMIT_MAX=20
UPLOAD_RATE_LIMIT_MAX=60
ADMIN_EMAIL=admin@quzuo.net
ADMIN_PASSWORD=q1w2e3r4
逐项说明:
| 变量 | 作用 | 本文取值说明 |
|---|---|---|
PUID / PGID | Postgres 进程运行的 uid/gid,须与 ./data/postgres 目录属主一致 | 默认 999(镜像内置 postgres 用户) |
POSTGRES_PASSWORD | 数据库 cleep 用户的密码 | 与 DATABASE_URL 中的密码段必须一致 |
DATABASE_URL | 应用连接数据库的完整串;compose 网络内主机名固定为服务名 postgres | postgres://cleep:<密码>@postgres:5432/cleep |
SESSION_SECRET | 会话 Cookie 签名密钥,必填无默认值,缺失时应用启动即失败 | openssl rand -hex 32 生成 |
PORT | 应用监听端口 | 默认 6169 |
COOKIE_SECURE | 是否给会话 Cookie 加 Secure 标志 | 仅当反向代理已终止 HTTPS 时设 true,否则登录后每个请求都会 401 |
TRUST_PROXY | 是否信任上游代理的 X-Forwarded-For(影响登录限流的客户端 IP 判定) | 仅在反向代理之后设 true,否则所有访客共享同一限流额度 |
AUTH_RATE_LIMIT_MAX | 每窗口登录/注册类请求上限 | 默认 20 |
UPLOAD_RATE_LIMIT_MAX | 每窗口上传/导入导出请求上限 | 默认 60 |
ADMIN_EMAIL / ADMIN_PASSWORD | 首次启动时引导创建的管理员账号;留空则不创建 | 两个变量必须同时设置才生效 |
⚠️ 注意:
.env含数据库密码与会话密钥,属敏感文件。 compose 官方模板已在 git 中忽略它;生产服务器上建议chmod 600 /opt/cleep/.env。
4.2 编写编排文件
创建 /opt/cleep/docker-compose.yml(与官方仓库自带模板一致,仅对外端口按本文规划发布为 8140):
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
user: "${PUID:-999}:${PGID:-999}"
environment:
POSTGRES_USER: cleep
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}
POSTGRES_DB: cleep
volumes:
- ./data/postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U cleep -d cleep"]
interval: 5s
timeout: 5s
retries: 10
app:
image: ghcr.io/blindpassasjer/cleep:latest
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
DATABASE_URL: ${DATABASE_URL:?Set DATABASE_URL in .env}
SESSION_SECRET: ${SESSION_SECRET:?Set SESSION_SECRET in .env}
ATTACHMENTS_DIR: /data/attachments
PORT: ${PORT:-6169}
NODE_ENV: production
COOKIE_SECURE: ${COOKIE_SECURE:-false}
TRUST_PROXY: ${TRUST_PROXY:-false}
AUTH_RATE_LIMIT_MAX: ${AUTH_RATE_LIMIT_MAX:-}
AUTH_RATE_LIMIT_WINDOW_MS: ${AUTH_RATE_LIMIT_WINDOW_MS:-}
UPLOAD_RATE_LIMIT_MAX: ${UPLOAD_RATE_LIMIT_MAX:-}
UPLOAD_RATE_LIMIT_WINDOW_MS: ${UPLOAD_RATE_LIMIT_WINDOW_MS:-}
ADMIN_EMAIL: ${ADMIN_EMAIL:-}
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-}
volumes:
- ./data/attachments:/data/attachments
ports:
- "8140:6169"
编排要点解读:
- 两个服务:
postgres(数据)与app(应用);depends_on: service_healthy保证数据库通过健康检查后才启动应用。 - 数据全部落宿主机普通目录:不用匿名卷,
./data/postgres与./data/attachments直接可浏览、可备份。 - 端口映射
8140:6169:左侧是对外发布端口(改成你规划的端口),右侧 6169 是应用监听端口(与PORT对应)。 - 健康检查:
pg_isready -U cleep -d cleep每 5 秒一次、最多重试 10 次。
4.3 拉取镜像
cd /opt/cleep
docker compose pull
实测回显(尾部节选,分层下载过程略):
6288ca1fda9c Extracting 1B
6288ca1fda9c Pull complete 0B
493c6ada4d66 Pull complete 0B
f1a36da7b02d Pull complete 0B
6bbd9b7ca1a1 Pull complete 0B
171591073c1f Pull complete 0B
1f145c2e42b2 Pull complete 0B
Image ghcr.io/blindpassasjer/cleep:latest Pulled
⚠️ 网络说明:
ghcr.io在国内网络下可能拉取缓慢或超时。本文实测环境为 Docker 守护进程配置代理(192.168.1.62:7897)后一次拉取成功;如遇超时,配置代理或镜像加速后重试本命令即可,无需改动其他步骤。
4.4 启动服务
docker compose up -d
实测回显:
Container cleep-020-stack-postgres-1 Starting
Container cleep-020-stack-postgres-1 Started
Container cleep-020-stack-postgres-1 Waiting
Container cleep-020-stack-postgres-1 Healthy
Container cleep-020-stack-app-1 Starting
Container cleep-020-stack-app-1 Started
(回显中的项目名称前缀因各服务器 compose 项目目录名不同而不同,属正常现象。)
4.5 验证启动结果
第一步确认两个服务都在运行、数据库为 healthy:
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
cleep-020-stack-app-1 ghcr.io/blindpassasjer/cleep:latest "./docker-entrypoint…" app 14 seconds ago Up 8 seconds 0.0.0.0:8140->6169/tcp, [::]:8140->6169/tcp
cleep-020-stack-postgres-1 postgres:16-alpine "docker-entrypoint.s…" postgres 14 seconds ago Up 13 seconds (healthy) 5432/tcp
第二步看应用日志,应出现「迁移 → 引导管理员 → 监听端口」三段完整过程:
docker compose logs app
实测回显:
app-1 | Running database migrations...
app-1 | Migrations applied.
app-1 | Bootstrapping admin account...
app-1 | bootstrapAdmin: created admin account for admin@quzuo.net.
app-1 | Starting server...
app-1 | Cleep self-host server listening on port 6169
六行日志的含义:Running database migrations... / Migrations applied. 表示数据库表结构自动迁移完成(无需手工建表);Bootstrapping admin account... / created admin account for admin@quzuo.net 表示按 .env 的 ADMIN_EMAIL/ADMIN_PASSWORD 创建了首个管理员;最后两行表示 HTTP 服务已在 6169 端口监听。
第三步验证 HTTP 可达与安全响应头:
curl -sI http://127.0.0.1:8140/ | head -8
实测回显:
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' https: http: blob: data:; media-src 'self' blob:; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
Permissions-Policy: camera=(self), microphone=(self), geolocation=(), payment=(), usb=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin
返回 200 且默认带全安全响应头(CSP、X-Frame-Options 等),说明服务正常。
第四步用管理员账号实际登录一次(API 方式,等价于浏览器登录动作):
curl -s -c /tmp/cleep-cookie.txt -X POST http://127.0.0.1:8140/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"admin@quzuo.net","password":"q1w2e3r4"}'
实测回显:
{"user":{"id":"aba48719-7d4b-44b6-82c7-963a2b0fa777","email":"admin@quzuo.net","username":"admin","role":"admin"},"error":null}
返回 role:"admin" 的管理员用户对象即登录成功。此后浏览器访问 http://<服务器IP>:8140,用同一账号登录即可进入便签网格界面。
💡 说明:Cleep 注册默认关闭(管理员建号制)。管理员登录后在设置页的 Users 管理面板里逐个创建其他用户;直接调注册接口会得到
{"user":null,"error":"Registration is currently closed."}(HTTP 403),这是设计行为而非故障(详见「九、常见问题」)。
五、数据持久化说明
Cleep 的数据分两类、全部落在宿主机普通目录(非匿名卷),可直接用文件工具管理:
| 数据 | 宿主机路径 | 内容 |
|---|---|---|
| 数据库 | /opt/cleep/data/postgres/ | 笔记正文、用户、会话、标签、链接预览缓存等(PostgreSQL 数据文件) |
| 附件 | /opt/cleep/data/attachments/ | 照片/视频/录音文件,按 <用户ID>/<笔记ID>/<文件名> 分层存放 |
实测:上传一张图片附件后,目录树真实落盘如下——
find /opt/cleep/data/attachments -type f
实测回显:
/opt/cleep/data/attachments/aba48719-7d4b-44b6-82c7-963a2b0fa777/cb983725-d38e-4ad5-b24f-e6332021dcdc/494c14fd-7e75-48a1-9b2b-56db9c302f29-t.png
数据库侧实测共 8 张表(psql -U cleep -d cleep -c '\dt' 回显节选):users、sessions、notes、labels、note_labels、attachments、link_previews、app_settings。
💡 说明:备份的最小单位就是「
/opt/cleep/data/postgres的一致性导出 +attachments目录打包」。官方仓库自带scripts/backup.sh(pg_dump + tar)与scripts/restore.sh,本文第九章给出一次真实备份回显,完整备份/恢复/巡检流程见本专栏《Cleep 0.4.4 日常运维手册》。
六、环境变量表
下表汇总 compose 模板引用的全部环境变量(默认值与语义以官方 .env.example,2026-10-25 查询为准);逐项深解与调参建议见本专栏《Cleep 0.4.4 配置参数详解》:
| 变量 | 必填 | 默认值 | 作用 |
|---|---|---|---|
SESSION_SECRET | 是 | 无(缺失即启动失败) | 会话 Cookie 签名密钥 |
DATABASE_URL | 是 | 无 | 应用连接 PostgreSQL 的连接串 |
POSTGRES_PASSWORD | 是 | 无 | 数据库密码,须与 DATABASE_URL 同步 |
PUID / PGID | 否 | 999 / 999 | Postgres 进程运行身份,须等于数据目录属主 |
PORT | 否 | 6169 | 应用监听端口 |
ADMIN_EMAIL / ADMIN_PASSWORD | 否 | 空 | 首启引导管理员账号(须成对设置) |
COOKIE_SECURE | 否 | false | Cookie Secure 标志,仅 HTTPS 反代后设 true |
TRUST_PROXY | 否 | false | 信任 X-Forwarded-For,仅反代后设 true |
AUTH_RATE_LIMIT_MAX / AUTH_RATE_LIMIT_WINDOW_MS | 否 | 20 / 60000 | 登录注册限流(次/毫秒窗口) |
UPLOAD_RATE_LIMIT_MAX / UPLOAD_RATE_LIMIT_WINDOW_MS | 否 | 60 / 60000 | 上传与导入导出限流 |
LINK_PREVIEW_RATE_LIMIT_MAX / LINK_PREVIEW_RATE_LIMIT_WINDOW_MS | 否 | 300 / 60000 | 链接预览限流 |
ATTACHMENTS_DIR | 否 | /data/attachments(compose 内置) | 附件存储目录,仅裸机部署时需显式设置 |
七、配置参数说明
本节说明部署期最常调整的三组参数,完整参数体系(含限流窗口、会话与 Cookie 细节、反向代理配合)见本专栏《Cleep 0.4.4 配置参数详解》。
- 改对外端口:只改 compose 文件
ports左侧(如"8080:6169"),应用监听端口PORT=6169保持不变;改完docker compose up -d生效。 - 反向代理 + HTTPS:代理终止 TLS 后必须把
.env中两项改为COOKIE_SECURE=true、TRUST_PROXY=true再重启应用,否则会出现「登录看似成功但每个接口 401」或「正常登录即触发 Too many requests」两个典型故障;启用COOKIE_SECURE=true后 Cleep 会同时发送 6 个月 max-age 的 HSTS 头,请确认该域名确实长期走 HTTPS。 - 更换数据库密码:
POSTGRES_PASSWORD只在数据库首次初始化时生效;已有数据的库改密码需同时改DATABASE_URL并在数据库内ALTER USER cleep PASSWORD,仅改.env会导致应用连不上库(见「九、常见问题」Q3)。
八、等价 docker run
不使用 Compose 时,以下两条命令与上文编排完全等价(网络、卷、健康检查依赖需手工保证顺序,先起数据库并等待其可连接):
# 1. 启动数据库(数据目录属主须为 999)
docker run -d --name cleep-postgres --restart unless-stopped \
--user 999:999 \
-e POSTGRES_USER=cleep -e POSTGRES_PASSWORD=cleepdb2026 -e POSTGRES_DB=cleep \
-v /opt/cleep/data/postgres:/var/lib/postgresql/data \
postgres:16-alpine
# 2. 启动应用(--link 仅示意,生产建议用自定义网络按服务名互访)
docker run -d --name cleep-app --restart unless-stopped \
-e DATABASE_URL=postgres://cleep:cleepdb2026@postgres:5432/cleep \
-e SESSION_SECRET=784e82cbbf04d24479a87fb9263bd51b836e8db2f09ddde4701dd0eeebfdd001 \
-e ATTACHMENTS_DIR=/data/attachments -e PORT=6169 -e NODE_ENV=production \
-e COOKIE_SECURE=false -e TRUST_PROXY=false \
-e ADMIN_EMAIL=admin@quzuo.net -e ADMIN_PASSWORD=q1w2e3r4 \
-v /opt/cleep/data/attachments:/data/attachments \
-p 8140:6169 \
ghcr.io/blindpassasjer/cleep:latest
💡 说明:两条
docker run需让两个实例处于同一自定义网络并能按主机名postgres解析(Compose 默认已处理好这一点);因此官方与本文都推荐 Compose 形态,等价命令仅作理解参数映射之用。
九、常用运维命令
以下命令均在 /opt/cleep/(compose 项目目录)下执行,全部实测通过:
# 查看服务状态
docker compose ps
# 跟踪应用日志
docker compose logs -f app
# 重启应用(改 .env 后)
docker compose restart app
# 升级到最新镜像(数据库迁移随启动自动执行)
docker compose pull && docker compose up -d
# 停止整套服务(数据目录保留)
docker compose down
重启后数据保持实测:docker compose restart app 后重新查询笔记列表,重启前创建的 2 条笔记均在(notes after restart: 2)。
备份实测:官方 scripts/backup.sh 在 compose 项目目录执行——
./backup.sh --keep 7
实测回显:
Dumping Postgres -> ./backups/20261025T042623Z/postgres.sql
Archiving attachments -> ./backups/20261025T042623Z/attachments.tgz
Done: ./backups/20261025T042623Z
Pruning old backups, keeping newest 7
产物为带时间戳的目录(postgres.sql 全量导出 + attachments.tgz 附件包 + README.txt 说明),--keep 7 表示只保留最新 7 份。恢复用 ./restore.sh ./backups/<时间戳>,本文实测删除一条笔记后从该备份完整恢复。完整操作与定时备份配置见本专栏《Cleep 0.4.4 日常运维手册》。
资源占用参考(实测,空闲状态):应用进程内存约 40MiB,PostgreSQL 约 80MiB——总计百兆级,适合低功耗 NAS。
十、常见问题
Q1:拉取 ghcr.io 镜像超时怎么办?
为 Docker 守护进程配置 HTTP 代理(/etc/docker/daemon.json 的 proxies 或 systemd drop-in)后 systemctl restart docker,重试 docker compose pull;也可先 docker login ghcr.io 排除匿名配额问题。本文实测经代理一次成功。
Q2:浏览器登录后立刻被踢回登录页 / 接口全 401?
绝大多数是 COOKIE_SECURE=true 但你仍在用 http:// 访问——带 Secure 的 Cookie 在 HTTP 下被浏览器静默丢弃。纯 HTTP 直连场景保持 COOKIE_SECURE=false;只有反向代理终止 HTTPS 后才设 true。
Q3:改了 .env 里的 POSTGRES_PASSWORD 后应用起不来?
POSTGRES_PASSWORD 仅在数据库首次初始化时写入;对已初始化的数据目录改密码需要三步同步:改 .env 两处(POSTGRES_PASSWORD 与 DATABASE_URL)→ 进数据库执行 ALTER USER cleep WITH PASSWORD '新密码'; → docker compose up -d。
Q4:注册接口返回 403 "Registration is currently closed."?
设计行为:Cleep 默认关闭公开注册(实测 GET /api/auth/registration-status 返回 {"open":false})。由管理员登录 Web 界面,在 Users 管理面板创建账号;管理员也可以在后台为重置密码的用户生成临时密码。
Q5:首次启动日志卡在 migrations 或报数据库连接失败?
按顺序排查:① data/postgres 目录属主是否为 999:999(PUID/PGID 默认值);② .env 中 DATABASE_URL 的密码段是否与 POSTGRES_PASSWORD 一致;③ docker compose logs postgres 是否已正常完成初始化。
Q6:手机浏览器为什么不能「添加到主屏幕」/离线使用?
PWA 安装与录音都要求安全上下文(HTTPS 或 localhost)。纯 http://<nas-ip>:8140 下这两项不可用(笔记本体不受影响);为站点套上任意反向代理的 TLS 证书后即解锁,同时记得设置 TRUST_PROXY=true。
十一、参考链接
- Cleep 官方仓库(含
.env.example与docker-compose.yml模板):https://github.com/blindpassasjer/cleep (查询日期 2026-10-25) - GHCR 镜像仓库:https://github.com/blindpassasjer/cleep/pkgs/container/cleep
- Cleep CHANGELOG(v0.4.4,2026-10-02):https://github.com/blindpassasjer/cleep/blob/main/CHANGELOG.md
- PostgreSQL 16 官方镜像:https://hub.docker.com/_/postgres
- 本站相关文档:《Cleep 0.4.4 介绍与选型指南》(本专栏)、《Cleep 0.4.4 配置参数详解》(本专栏)、《Cleep 0.4.4 日常运维手册》(本专栏)