Sign inSign up

ignimutos/knock

By ignimutos

Updated 13 days ago

Knock is a Bun + TypeScript subscription fetch and delivery daemon.

Image
0

4.5K

ignimutos/knock repository overview

Knock

Knock 是一个基于 Bun + TypeScript 的订阅抓取与投递守护进程。

它可以抓取 RSS / Atom / JSON Feed,或通过 XQuery 从 HTML/XML 提取条目;随后统一 feed 与 entry 字段,执行 Liquid 过滤与渲染,并将结果投递到 file、push(HTTP)、email 通道,同时把状态与去重信息写入 SQLite。

镜像约定

  • 工作目录:/app
  • 默认运行目录:/app/runtime
  • 默认环境变量:KNOCK_RUNTIME_DIR=/app/runtime
  • 支持的容器启动默认变量:KNOCK_CONFIG_PATHKNOCK_IMMEDIATEKNOCK_ONCE
  • 容器默认通过 /app/docker-entrypoint.sh 启动:先执行 runtime 权限自检/修复,再启动主程序
  • 默认主程序:/app/knock-linux-x64,内部仍复用 src/container_entrypoint.ts 的参数归一化语义,默认直接以 daemon 运行
  • 构建阶段固定使用 oven/bun:1.3.13
  • 运行阶段固定使用 debian:bookworm-slim,并内置 CA 证书与 tzdata
  • 运行镜像不再携带 src/、完整 node_modules/ 或前端构建产物;仅保留二进制运行时需要的 jsdomcss-treemdn-data 资产目录
  • 发布前门禁固定执行:bun run verify:fullbun run build:binarybun run smoke:binarybun run image:prepare
  • 已发布标签:latestsha-<git-sha>

准备配置

先在宿主机准备 runtime/config.yml。最小示例:

sqlite:
  path: knock.db

deliveries:
  local:
    file:
      path: outputs/releases.md
      content: |
        ## [{{ entry.title }}]({{ entry.link }})

        {{ entry.content | strip_html }}

        ---

sources:
  bun:
    http:
      url: https://github.com/oven-sh/bun/releases.atom
    deliveries:
      local: {}

config.yml 支持 ${ENV_VAR} 展开;sqlite.pathdeliveries.*.file.path 的相对路径都相对 /app/runtime 解析。

SQLite 数据与损坏恢复
  • facts 库默认落在 /app/runtime/<sqlite.path>,是派生缓存数据:损坏后删除文件(连同同名 -wal / -shm)重启即可重建,或从备份恢复。
  • 启动时会先做一次页面级完整性校验;数据库损坏/非法会以 fatal 中止并给出恢复提示,而不是延迟到抓取/清理阶段才崩溃。
  • 若把 /app/runtime bind mount 到不可靠文件系统(网络盘、跨主机共享、部分虚拟化挂载)并反复出现 SQLITE_CORRUPT,建议在配置中显式设置 sqlite.journalMode: DELETE,并保证单实例运行与优雅停止。

容器启动相关环境变量:

  • 镜像内置:KNOCK_RUNTIME_DIR=/app/runtime
  • 可选覆盖:KNOCK_CONFIG_PATH=/app/runtime/config.yml
  • 可选覆盖:KNOCK_IMMEDIATE=true|false
  • 可选覆盖:KNOCK_ONCE=true|false

这些变量只在镜像默认入口下生效;挂载到 /app/runtimeconfig.yml 会被默认读取。src/container_entrypoint.ts 默认直接以 daemon 运行:KNOCK_CONFIG_PATH 会注入为 CLI --configKNOCK_IMMEDIATE / KNOCK_ONCE 会按约定注入为 --immediate / --once。若 docker run 里显式追加了对应 CLI 参数,则 CLI 参数优先。

一次性执行 daemon

docker run --rm \
  -v "$(pwd)/runtime:/app/runtime" \
  -e KNOCK_ONCE=true \
  <image>

默认入口会在启动时检查 KNOCK_RUNTIME_DIR 解析后的运行目录(默认 /app/runtime);当容器当前以 root 启动时,会递归修复该目录整棵树的 owner 与 u+rwXg+rwX 权限,然后再降权启动主程序。

这里的 <image> 请替换成当前 Docker Hub 仓库名,例如 <namespace>/knock:latest

启动常驻模式

docker run -d \
  --name knock \
  -v "$(pwd)/runtime:/app/runtime" \
  <image>

常见用法

  • 指定配置文件:docker run --rm -e KNOCK_CONFIG_PATH=/app/runtime/config.yml <image>
  • 立即执行一次后退出(当前进程会返回):docker run --rm -e KNOCK_ONCE=true <image>
  • 启动时立即执行一次并继续常驻(短窗口内不会返回):docker run --rm -e KNOCK_IMMEDIATE=true <image>
  • 显式参数覆盖环境变量:docker run --rm -e KNOCK_CONFIG_PATH=/app/runtime/config.yml <image> --config /other.yml

如果你通过环境变量注入 provider 凭据、SMTP 配置或 webhook URL,直接在 docker run 时追加 -e KEY=value 即可;入口脚本只会补齐未显式传入的 CLI 参数。默认建议不传 --user,让入口在启动时先自检并尝试修复 KNOCK_RUNTIME_DIR 解析后的运行目录权限。--user 仍可作为高级覆盖:仅在你需要强制指定容器进程 UID/GID 时使用;若显式传入非 root --user,则视为你主动放弃自动修权,并需自行保证目标 runtime 目录可写。

本仓库 CI 会先做三层门禁:

  1. verifybun run verify:full
  2. imagebun run image:prepare(构建并校验镜像体积)
  3. publish:仅 main 推送 linux/amd64 镜像并同步 Docker Hub README

镜像体积默认预算由 KNOCK_IMAGE_MAX_SIZE_MB 控制,CI 当前使用 450 MB。

Tag summary

Content type

Image

Digest

sha256:eb8f06ea5

Size

84.3 MB

Last updated

13 days ago

docker pull ignimutos/knock