Chhoto URL 7.10.3 Docker Compose 部署指南

Chhoto URL 7.10.3 Docker Compose 部署实测:镜像档位选择、compose.yaml 逐项配置与启动日志解读、healthz 健康检查、建链跳转与 hits 异步落库踩坑、数据持久化与自动备份验证(2026-10-30 实测)。

Chhoto URL自托管2026/10/30

Chhoto URL 7.10.3 Docker Compose 部署指南

目标:本文是 Chhoto URL 的部署篇,给出 Docker Compose 主形态下从零到可用的完整路径:镜像档位选择、compose.yaml 逐项配置、启动日志逐行解读、健康检查、建链跳转实测、数据持久化与自动备份验证。全部命令与输出基于 v7.10.3 容器实测(2026-10-30,单机 Docker 环境),选型与架构认知见《Chhoto URL 介绍与选型指南》。

一、部署前准备

1.1 环境要求

项目要求本篇实测环境
容器运行时Docker 24+(官方支持 Docker 与 Podman)Docker 29.x
编排工具Docker Compose v2(docker compose 子命令)Compose v2
端口规划宿主任选端口 → 容器固定 4567(应用监听端口硬编码,只能改映射侧)8130 → 4567
数据目录无需预建,使用 named volume 挂载 /datachhoto-url-7103-stack_data
磁盘占用镜像 alpine 档压缩后 <10 MB,数据库初始约 45 KB首启后卷内约 180 KB

Compose 环境本身尚未就绪的,先参考《Docker Compose 安装与多容器编排》完成安装;CHHOTO_* 环境变量属于进程级配置,与 Docker 守护进程配置(参见《Docker daemon.json 配置参数详解》)互不影响。

1.2 镜像档位选择

Chhoto URL 官方在 Docker Hub 与 GHCR 双渠道发布同一镜像(dev 系仅 GHCR),同一 tag 覆盖 amd64/arm64/armv7/riscv64 四架构。v7.10.3 可用的三个档位:

镜像档位基础特点健康检查
sintan1729/chhoto-url:latest(scratch)空镜像压缩后 <6 MB,无 shell、无 wget不可用官方 wget 探针,需改用 CMD 直连探测或放弃
sintan1729/chhoto-url:alpinealpine压缩后 <10 MB,含 wget 等基础工具官方 compose 样例原生支持
ghcr.io/sintan1729/chhoto-url:devalpine开发测试版,官方明确不建议生产同 alpine

本篇选 alpine 档:官方 compose 样例的 healthcheck 依赖容器内 wget,scratch 档没有。除非对镜像体积有极端要求,alpine 档是兼顾可运维性的默认选择。

二、compose.yaml 编写(主形态)

2.1 实测同款完整配置

name: chhoto-url-7.10.3-stack

services:
  chhoto-url:
    image: sintan1729/chhoto-url:alpine
    container_name: chhoto-url-7.10.3-web
    restart: unless-stopped
    tty: true
    ports:
      - "8130:4567"
    environment:
      - CHHOTO_DB_URL=/data/urls.sqlite
      - CHHOTO_SQLITE_USE_WAL_MODE=True
      - CHHOTO_PASSWORD=CHANGE_ME_STRONG_PASS   # 管理密码,生产必须修改;支持 Argon2 哈希
      - CHHOTO_EXIT_ON_NO_AUTH=True             # 未配置任何认证时拒绝启动,防裸奔
      - CHHOTO_API_KEY=CHANGE_ME_LONG_APIKEY    # 程序调用用 API Key,与密码二选一也可
      - CHHOTO_REDIRECT_METHOD=TEMPORARY        # 307 临时跳转,避免浏览器缓存映射
      - CHHOTO_SLUG_STYLE=Pair                  # 形容词-名词对风格短链
      - CHHOTO_SITE_URL=http://192.168.1.200:8130   # 对外访问地址,影响生成短链的前缀
    volumes:
      - data:/data
    healthcheck:
      test: wget -qO- http://127.0.0.1:1729/healthz || exit 1
      interval: 60s
      start_period: 10s
      retries: 3
      timeout: 10s

volumes:
  data:

2.2 逐项说明

配置项取值说明
ports8130:4567应用进程固定监听 4567(官方硬编码,容器内无对应环境变量),改宿主侧即可
CHHOTO_DB_URL/data/urls.sqliteSQLite 数据库文件路径,必须落在卷内才有持久化
CHHOTO_SQLITE_USE_WAL_MODETrue开启 WAL 日志模式,官方强烈建议;启动日志会打印 Using WAL journaling mode
CHHOTO_PASSWORD明文或 Argon2 哈希管理界面与 API 共用;明文时启动日志出现 WARN,建议预存 Argon2 哈希
CHHOTO_EXIT_ON_NO_AUTHTrue密码与 OIDC 都未配置时进程直接退出(退出码 1),防止无认证暴露公网
CHHOTO_API_KEY长随机串供 REST API 调用方使用,请求头 X-API-Key,详见本专栏 API 篇
CHHOTO_REDIRECT_METHODTEMPORARY / PERMANENT对应 HTTP 307 / 308,默认 PERMANENT;本篇实测用 TEMPORARY
CHHOTO_SLUG_STYLEPair / UIDPair 生成「形容词-名词」易读短链;UID 为随机字符串
CHHOTO_SITE_URL对外可达地址创建短链时返回的 shorturl 前缀取自这里,填错不影响跳转只影响展示
restartunless-stopped守护进程重启后自动拉起,手工 stop 则不拉
tty: true—保持标准输出可用,便于 docker logs 观察访问日志
healthcheckwget → 127.0.0.1:1729应用在回环地址额外监听 /healthz,返回 healthy/unhealthy,不占用对外端口

三、启动与首启验证

3.1 拉起与启动日志

docker compose up -d
docker logs -f chhoto-url-7.10.3-web

v7.10.3 首启日志实测摘录(去掉颜色码,按顺序):

Starting Chhoto URL Server v7.10.3
Allowed protocols: {"ftp", "magnet", "https", "http"}
WARN Using plaintext for password and API key verification. Argon2 is advised.
Configured Site URL: http://192.168.1.200:8130
Using adjective-noun pair slugs.
Capital letters won't be allowed in links.
Using WAL journaling mode for database.
Ensuring ACID compliance, using synchronous pragma: FULL.
Creating an init backup of the database.
Initializing database.
Database initialization was successful.
Server has started listening to 0.0.0.0 on port 4567.
Starting database cleanup service, will run once every hour.
No expired links were found.

逐行解读:允许的长链协议白名单默认 4 种(可追加);密码/API Key 为明文时给出 Argon2 建议(WARN 不阻断);随后依次回显站点地址、短链风格、大小写策略、WAL 与 ACID 级别;每次容器首启都会先做一次数据库初始化备份再建库;过期短链清理服务每小时跑一次。

3.2 健康检查确认

/healthz 只绑定在容器内 127.0.0.1:1729,不通过 4567 对外暴露,属专用存活探针端点:

docker exec chhoto-url-7.10.3-web wget -qO- http://127.0.0.1:1729/healthz
# 输出:healthy
docker ps --filter name=chhoto-url --format '{{.Status}}'
# 输出:Up (healthy)

3.3 无认证快速探针

两个只读路由无需任何认证,是部署后确认服务存活最快的探针(官方 docs/CLI.md 口径,实测输出):

curl http://localhost:8130/api/version   # → Chhoto URL v7.10.3
curl http://localhost:8130/api/siteurl   # → http://192.168.1.200:8130

带认证的 /api/getconfig 能一次性回显生效配置,适合核对环境变量是否按预期加载(输出节选):

{"version":"7.10.3","site_url":"http://192.168.1.200:8130","allow_capital_letters":false,
 "public_mode":false,"allowed_protocols":["ftp","magnet","https","http"],
 "slug_style":"Pair","slug_length":8,"try_longer_slug":false,"frontend_page_size":10}

四、建链与跳转实测

4.1 创建短链

REST 方式创建(也可在网页管理界面操作,二者等价):

# 自定义短链别名
curl -s -X POST -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{"longlink": "https://www.quzuo.net/", "shortlink": "quzuo-home"}' \
  http://localhost:8130/api/new
# → {"success":true,"error":false,"shorturl":"http://192.168.1.200:8130/quzuo-home","enabled":true,"expiry_time":0}

# 不传 shortlink,Pair 风格自动生成
curl -s -X POST -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{"longlink": "https://docs.quzuo.net/guide/intro?tab=advanced&v=2"}' \
  http://localhost:8130/api/new
# → {"success":true,...,"shorturl":"http://192.168.1.200:8130/buck-elastic",...}

自动生成的 buck-elastic 正是「形容词-名词」对格式;长链接里的查询串与多参数原样保留。

4.2 跳转语义实测

curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" http://localhost:8130/quzuo-home
# → 307 -> https://www.quzuo.net/

CHHOTO_REDIRECT_METHOD=TEMPORARY 生效为 307 临时跳转,浏览器每次访问都会回源询问,改目标地址后立即生效;若为 PERMANENT 则返回 308,浏览器可能长期缓存旧映射。

4.3 两个实测踩坑

踩坑一:HEAD 请求 404,探针必须用 GET。 用 curl -I(HEAD 方法)访问短链会得到 404 页面,而同一 URL 的 GET 请求正常 307——v7.10.3 的跳转路由只注册了 GET 语义,HEAD 会落入 404 兜底分支,且不产生命中计数。监控脚本、拨测工具若以 HEAD 探活短链会全部误报,务必改用 GET 探测。

踩坑二:hits 计数为异步批量落库,初查为 0 系探针过快。 访问短链后立刻查询 /api/all,hits 仍显示旧值甚至 0:命中计数经内存通道由后台 worker 批量写库(实测约 500 ms~1 s 内可见 +1)。正确姿势是访问后等待 1 秒以上再查,不要把「计数不涨」误判为统计失效。

五、数据持久化与自动备份

5.1 卷内数据结构

named volume 挂载在 /data,实测文件布局:

/data
├── urls.sqlite                          # 主数据库(WAL 模式下约 45 KB 起)
├── urls.sqlite-wal                      # WAL 预写日志(运行中 90 KB 上下浮动)
├── urls.sqlite-shm                      # WAL 共享内存索引
└── backups/
    ├── urls.sqlite.init.2026-10-30T04-06-34Z    # 首启 init 备份
    └── urls.sqlite.init.2026-10-30T04-08-33Z    # 第二次容器首启又做一次 init 备份

自动备份策略(官方口径):初始化时与每日 3-4 点间各备份一次,保留最近 3 份初始化备份与 7 份每日备份;如需接管备份节奏可用 CHHOTO_DISABLE_BACKUPS 关闭后自建定时任务,SQLite 层面的备份/恢复方法可参考《SQLite 备份与恢复指南》。

5.2 容器重建实测

docker compose down(不带 -v)后重新 up -d,验证数据保留:

重建后: 4 条
  docs              https://www.quzuo.net      hits 4
  franklin-stupefied https://example.com       hits 0
  quzuo-home        https://www.quzuo.net/     hits 3
  buck-elastic      https://docs.quzuo.net/... hits 0
跳转验证: 307 -> https://www.quzuo.net/

短链、命中计数、备注、过期设置全部保留,重建后跳转立即恢复。注意:down -v 会连卷一起删除,等价于清库重来,日常维护只用 down/restart。

六、升级、安全加固与 HTTPS 前置

  • 升级:docker compose pull && docker compose up -d,数据在卷内不动;升级后用 /api/version 复查版本号。
  • 密码加固:日志 WARN 的 Argon2 建议值得落实——把明文密码换为 Argon2 哈希存入 CHHOTO_PASSWORD,即使环境变量泄露也不能直接反推原密码。
  • HTTPS:应用本身不做 TLS,管理密码以明文穿过网络,生产必须前置反代。Caddy 方案可参考《Caddy 2.11.7 Docker Compose 部署指南》与《Caddy 2 配置参数详解》,Nginx 方案可参考《Nginx 配置参数详解》;反代只需把 Host 头透传到 4567 即可,短链跳转由应用自己完成。
  • 端口收敛:若只经反代访问,可把 ports 映射改为 127.0.0.1:8130:4567,避免管理面裸露在内网之外。

七、排错清单

现象原因处置
curl -I 访问短链返回 404HEAD 方法不命中跳转路由(v7.10.3 行为)改用 curl -s -o /dev/null -w "%{http_code}" 的 GET 探针
访问后 hits 立即查询为 0命中计数异步批量落库(约 500 ms~1 s)等待 1 秒后再查,勿误判统计失效
容器启动即退出(exit 1)未配置任何认证且 CHHOTO_EXIT_ON_NO_AUTH=True配置 CHHOTO_PASSWORD 或 OIDC 后重启
日志 WARN 提示 Argon2密码/API Key 为明文存储换用 Argon2 哈希写入环境变量
docker logs 无访问日志未开 tty 或未加 Compress/Logger 中间件对应配置compose 加 tty: true 后重建容器
短链跳转 404 但列表里存在访问的短链名与库里大小写不一致allow_capital_letters=false 时别名强制小写,统一用小写访问
管理界面打不开CHHOTO_DISABLE_FRONTEND=True 关闭了前端去掉该变量重建,或纯走 API

八、本专栏系列导航

  • 认知与选型:《Chhoto URL 介绍与选型指南》——架构、特性与同类对比。
  • 下一篇:配置参数详解(CHHOTO_* 环境变量全集与生效验证)、REST API 使用详解将陆续发布于本专栏。