From b1f97c105a442ca5dfac3409938c2dc753ad30c2 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Mon, 15 Jun 2026 10:58:05 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=85=D1=80=D0=B0=D0=BD=D0=B8=D0=BC=D1=8B=D0=B5=20?= =?UTF-8?q?=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=BF=D0=BE=20=D1=81?= =?UTF-8?q?=D0=BB=D0=BE=D1=8F=D0=BC:=20config,=20data,=20cache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 7 +++++-- README.md | 7 ++++--- cmd/jellybit/healthcheck.go | 2 +- cmd/jellybit/recognize.go | 2 +- cmd/jellybit/serve.go | 2 +- docs/specs/architecture.md | 12 ++++++++---- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1e82273..366e070 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,9 @@ # CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o jellybit ./cmd/jellybit # distroless/static несёт CA-сертификаты (HTTPS к LLM/TMDB). Пользователь # задаётся в compose (user: "1000:1000"). +# +# Тома (см. compose): /config (ro, рендерится плейбуком — восстановимо при +# деплое) + /data (SQLite, бекапить-и-не-терять). FROM gcr.io/distroless/static-debian12 COPY jellybit /usr/local/bin/jellybit @@ -10,8 +13,8 @@ COPY jellybit /usr/local/bin/jellybit EXPOSE 8080 # В distroless нет shell/curl — проверку делает сам бинарь (порт берёт из -# /data/config.toml). compose может переопределить параметры healthcheck. +# /config/config.toml — дефолтный путь). compose может переопределить параметры. HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD ["/usr/local/bin/jellybit", "healthcheck"] -ENTRYPOINT ["/usr/local/bin/jellybit", "--config", "/data/config.toml"] +ENTRYPOINT ["/usr/local/bin/jellybit", "--config", "/config/config.toml"] diff --git a/README.md b/README.md index 300ca47..1696736 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ jellybit recognize --dry-run [--context "..."] --config ./config.toml бинарь: `jellybit healthcheck` (GET `/healthz` по порту из конфига, exit 0/1). Контейнер: `user 1000:1000`, порт `8080` на хост, mount `/srv/media` (единая -песочница для хардлинков) + data-том с `config.toml`/SQLite; к qBittorrent — -по сети Docker. Конкретная деплой-обвязка (плейбук, секреты) держится в -отдельном приватном репозитории и в комплект не входит. +песочница для хардлинков) + том `/config` (ro, `config.toml`, восстановим при +деплое) + data-том `/data` (SQLite, бекапить); к qBittorrent — по сети Docker. +Конкретная деплой-обвязка (плейбук, секреты) держится в отдельном приватном +репозитории и в комплект не входит. diff --git a/cmd/jellybit/healthcheck.go b/cmd/jellybit/healthcheck.go index 3cd9732..a332a37 100644 --- a/cmd/jellybit/healthcheck.go +++ b/cmd/jellybit/healthcheck.go @@ -16,7 +16,7 @@ import ( // нет shell/curl: docker зовёт сам бинарь. func runHealthcheck(args []string) error { fs := flag.NewFlagSet("healthcheck", flag.ContinueOnError) - configPath := fs.String("config", "/data/config.toml", "путь к config.toml") + configPath := fs.String("config", "/config/config.toml", "путь к config.toml") if err := fs.Parse(args); err != nil { return err } diff --git a/cmd/jellybit/recognize.go b/cmd/jellybit/recognize.go index e1a5604..edeb2f1 100644 --- a/cmd/jellybit/recognize.go +++ b/cmd/jellybit/recognize.go @@ -23,7 +23,7 @@ import ( // Только чтение: ни записи в БД, ни хардлинков. func runRecognize(args []string) error { fs := flag.NewFlagSet("recognize", flag.ContinueOnError) - configPath := fs.String("config", "/data/config.toml", "путь к config.toml") + configPath := fs.String("config", "/config/config.toml", "путь к config.toml") dryRun := fs.Bool("dry-run", true, "только показать план, без изменений (единственный режим)") contextStr := fs.String("context", "", "доп. текстовый контекст для распознавания") if err := fs.Parse(args); err != nil { diff --git a/cmd/jellybit/serve.go b/cmd/jellybit/serve.go index 856afc4..3aa6e8f 100644 --- a/cmd/jellybit/serve.go +++ b/cmd/jellybit/serve.go @@ -33,7 +33,7 @@ import ( // воркер (фоном) → HTTP-сервер; останавливается по SIGINT/SIGTERM. func runServe(args []string) error { fs := flag.NewFlagSet("serve", flag.ContinueOnError) - configPath := fs.String("config", "/data/config.toml", "путь к config.toml") + configPath := fs.String("config", "/config/config.toml", "путь к config.toml") if err := fs.Parse(args); err != nil { return err } diff --git a/docs/specs/architecture.md b/docs/specs/architecture.md index d30de34..4b610f9 100644 --- a/docs/specs/architecture.md +++ b/docs/specs/architecture.md @@ -283,7 +283,8 @@ Jellyfin ([jellyfin-layout.md](jellyfin-layout.md)). Правила: - **qBit** — `savepath=/srv/media/downloads`, temp `/srv/media/incomplete`. - **jellybit** — читает `downloads`, пишет в `movies`/`series`; свой - SQLite/конфиг — отдельным mount'ом `/srv/applications/jellybit/data`. + SQLite — отдельным mount'ом `/srv/applications/jellybit/data`, конфиг — + отдельным `/srv/applications/jellybit/config`. - **Jellyfin** — библиотеки указывают на `movies`/`series` (не на корень `/srv/media`, иначе в индекс попадут downloads/incomplete). @@ -323,10 +324,13 @@ Jellybit работает в **docker** — в одной среде с qBittorr - **`user: "1000:1000"`**, UMASK 022 — единый системный пользователь umbar; созданные каталоги 0755, файлы-ссылки наследуют inode источника. - **mount `/srv/media`** (единая песочница) — для хардлинков и move - (см. «Пути и контейнеры»); `/srv/applications/jellybit/data` — отдельно. + (см. «Пути и контейнеры»); каталоги jellybit — отдельно. +- **mount конфига** `/srv/applications/jellybit/config` → `/config` (ro): + `config.toml` (0600). Восстановим при деплое (рендерит плейбук umbar) — + бекапить не нужно. - **mount данных** `/srv/applications/jellybit/data` → `/data`: SQLite - (`/data/jellybit.db`) и `config.toml`. Без него редеплой стёр бы всё - in-flight состояние. + (`/data/jellybit.db`). Бекапить-и-не-терять — без него редеплой стёр бы + всё in-flight состояние. - **healthcheck** на `/healthz`. Разделение ответственности: