From 7f35d32f3e08b6f765ac8ca1e6835b2b0278a1fa Mon Sep 17 00:00:00 2001 From: mARTin-B78 Date: Fri, 29 May 2026 15:31:46 +0200 Subject: [PATCH] Replace named Docker volume with local bind-mount folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit config/ and logs/ are now host directories visible on the filesystem. - docker-compose.yml: ./config → /home/app/.config/tts-voice-creator:rw ./logs → /logs:rw Named volume tts-voice-creator-clone-and-design-2 removed. - portainer-stack.yml: same change with absolute host paths. - server.py: RotatingFileHandler writes INFO+ to /logs/app.log (maxBytes=5MB, backupCount=3). Falls back gracefully if /logs is not writable. - .gitignore: track config/ and logs/ dirs via .gitkeep but exclude settings.json, *.log and backups from version control. Benefits: - Settings and logs are human-readable on the host at any time - Survives docker-compose down -v (was lost with named volume) - Easy backup: cp -r config/ logs/ to any destination - Can edit settings.json directly if needed Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 7 +++++++ CHANGELOG.md | 14 ++++++++++++++ config/.gitkeep | 0 docker-compose.yml | 6 ++---- logs/.gitkeep | 0 portainer-stack.yml | 6 ++---- server.py | 23 +++++++++++++++++++++++ 7 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 config/.gitkeep create mode 100644 logs/.gitkeep diff --git a/.gitignore b/.gitignore index f85438f..66298e3 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,10 @@ voice_design_presets.json # Personal documentation (not part of the public repo) APP_ERKLÄRUNG.md + +# Local bind-mount data — keep directory, ignore contents +config/settings.json +config/voice_design_presets.json +config/tts_routes.json +logs/*.log +logs/*.log.* diff --git a/CHANGELOG.md b/CHANGELOG.md index a55a19b..a258613 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,20 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi ## [Unreleased] +### Changed + +- **Config and logs are now bind-mounted local folders** — replaced the + opaque named Docker volume (`tts-voice-creator-clone-and-design-2`) with + two transparent host directories: + - `./config/` → `/home/app/.config/tts-voice-creator` — holds + `settings.json`, `voice_design_presets.json`, `tts_routes.json` + - `./logs/` → `/logs` — holds `app.log` (rotates at 5 MB, 3 backups) + Both directories are tracked in git (via `.gitkeep`) but their runtime + contents are excluded from version control via `.gitignore`. + `portainer-stack.yml` updated with absolute host paths. +- **Server writes a rotating log file** — `RotatingFileHandler` added to + `server.py`; writes `INFO`-level and above to `./logs/app.log`. + ### Fixed - **Engine settings lost after container recreate** — container names and diff --git a/config/.gitkeep b/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yml b/docker-compose.yml index c691810..06b9e51 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,8 @@ services: volumes: - ${VOICE_HOST_DIR:-./voices}:/voices:rw - - tts-voice-creator-clone-and-design-2:/home/app/.config/tts-voice-creator + - ./config:/home/app/.config/tts-voice-creator:rw # settings, presets, routes + - ./logs:/logs:rw # application logs - /var/run/docker.sock:/var/run/docker.sock:ro - ./static:/app/static:ro - ./server.py:/app/server.py:ro @@ -37,9 +38,6 @@ services: networks: - dgx_net -volumes: - tts-voice-creator-clone-and-design-2: - networks: dgx_net: external: true diff --git a/logs/.gitkeep b/logs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/portainer-stack.yml b/portainer-stack.yml index 37c994d..f1616a8 100644 --- a/portainer-stack.yml +++ b/portainer-stack.yml @@ -27,7 +27,8 @@ services: volumes: - /home/sparky/Projekte/TTS_Voices:/voices:rw - - tts-voice-creator-clone-and-design-2:/home/app/.config/tts-voice-creator + - /home/sparky/Docker/tts-voice-creator-clone-and-design-2/config:/home/app/.config/tts-voice-creator:rw + - /home/sparky/Docker/tts-voice-creator-clone-and-design-2/logs:/logs:rw - /var/run/docker.sock:/var/run/docker.sock:ro # ── Hot-reload mounts (changes apply on container recreate, not restart) ── - /home/sparky/Docker/tts-voice-creator-clone-and-design-2/server.py:/app/server.py:ro @@ -48,9 +49,6 @@ services: networks: - dgx_net -volumes: - tts-voice-creator-clone-and-design-2: - networks: dgx_net: external: true diff --git a/server.py b/server.py index 0c55c6d..66abbd6 100644 --- a/server.py +++ b/server.py @@ -2,6 +2,9 @@ from __future__ import annotations import logging +import os +from logging.handlers import RotatingFileHandler +from pathlib import Path from fastapi import FastAPI from fastapi.staticfiles import StaticFiles @@ -21,6 +24,26 @@ _buf_handler = _BufferHandler() _buf_handler.setLevel(logging.DEBUG) logging.getLogger().addHandler(_buf_handler) +# ── File log handler (rotates at 5 MB, keeps 3 files) ──────────────────────── + +_LOG_DIR = Path(os.environ.get("LOG_DIR", "/logs")) +try: + _LOG_DIR.mkdir(parents=True, exist_ok=True) + _file_handler = RotatingFileHandler( + _LOG_DIR / "app.log", + maxBytes=5 * 1024 * 1024, + backupCount=3, + encoding="utf-8", + ) + _file_handler.setLevel(logging.INFO) + _file_handler.setFormatter(logging.Formatter( + "%(asctime)s %(levelname)-8s %(name)s: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + )) + logging.getLogger().addHandler(_file_handler) +except Exception as _log_err: + logger.warning("Could not set up file logging at %s: %s", _LOG_DIR, _log_err) + # ── Routers ─────────────────────────────────────────────────────────────────── app.include_router(admin.router)