From de62a27fb6ed295572b87cacc16fd418b1a9de7a Mon Sep 17 00:00:00 2001 From: thefux Date: Thu, 6 Aug 2026 19:57:27 +0000 Subject: [PATCH 1/2] fix(docker): exclude runtime state from build context --- .dockerignore | 50 ++++++++++++++++++++++--- tests/unit/test_docker_build_context.py | 41 ++++++++++++++++++++ 2 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 tests/unit/test_docker_build_context.py diff --git a/.dockerignore b/.dockerignore index 4018f08a..32b3df31 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,13 +1,51 @@ -.env -.venv +# Git and repository metadata .git .gitignore .dockerignore -compose.yml -compose.testing.yml -.todo .github .vscode .DS_Store +.todo + +# Local configuration and secrets +.env +.env.* +routstr_secret.key + +# Python environments, caches, and build artifacts +.venv +__pycache__ +*.py[cod] +.pytest_cache +.mypy_cache +.ruff_cache +.coverage +htmlcov +*.egg-info +build +dist + +# Runtime state must never be baked into the image +logs +logs.* +*.log +.wallet +.cashu +*.db +*.db-* +*.sqlite3 +keys +proof_backups +relay-data + +# The UI is built by its own service and mounted at runtime +ui +ui_out **/node_modules -ui/.next + +# Compose and local development files +compose.yml +compose.testing.yml +compose.override.yml +plans +.worktrees diff --git a/tests/unit/test_docker_build_context.py b/tests/unit/test_docker_build_context.py new file mode 100644 index 00000000..a0637bbc --- /dev/null +++ b/tests/unit/test_docker_build_context.py @@ -0,0 +1,41 @@ +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] + + +def test_backend_docker_context_excludes_generated_and_runtime_state() -> None: + patterns = { + line.strip() + for line in (REPO_ROOT / ".dockerignore").read_text().splitlines() + if line.strip() and not line.lstrip().startswith("#") + } + + required_patterns = { + "__pycache__", + "*.py[cod]", + ".pytest_cache", + ".mypy_cache", + ".ruff_cache", + ".coverage", + "*.egg-info", + "build", + "dist", + "logs", + "logs.*", + ".wallet", + ".cashu", + "*.db", + "*.db-*", + "*.sqlite3", + "keys", + "proof_backups", + "relay-data", + "ui", + "ui_out", + } + + assert required_patterns <= patterns, ( + "The backend Docker context must exclude local build artifacts and " + f"runtime state; missing patterns: {sorted(required_patterns - patterns)}" + ) From bc5c56ecc3f8879c8b42785a478af1fed901563f Mon Sep 17 00:00:00 2001 From: 9qeklajc Date: Thu, 6 Aug 2026 22:58:44 +0200 Subject: [PATCH 2/2] clean up --- .dockerignore | 52 +++++++++++++------------ tests/unit/test_docker_build_context.py | 45 ++++++++++++--------- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/.dockerignore b/.dockerignore index 32b3df31..70a02164 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,39 +8,41 @@ .todo # Local configuration and secrets -.env -.env.* -routstr_secret.key +**/.env +**/.env.* +**/routstr_secret.key # Python environments, caches, and build artifacts -.venv -__pycache__ -*.py[cod] -.pytest_cache -.mypy_cache -.ruff_cache -.coverage -htmlcov -*.egg-info -build -dist +**/.venv +**/__pycache__ +**/*.py[cod] +**/.pytest_cache +**/.mypy_cache +**/.ruff_cache +**/.coverage +**/htmlcov +**/*.egg-info +**/build +**/dist # Runtime state must never be baked into the image logs logs.* -*.log -.wallet -.cashu -*.db -*.db-* -*.sqlite3 -keys -proof_backups -relay-data +**/*.log +**/.wallet* +**/.cashu +**/*.db +**/*.db-* +**/*.sqlite3 +**/*.sqlite3-* +**/keys +**/proof_backups +**/relay-data -# The UI is built by its own service and mounted at runtime -ui +# The UI output is built by its own service and mounted at runtime ui_out +ui/.next +ui/out **/node_modules # Compose and local development files diff --git a/tests/unit/test_docker_build_context.py b/tests/unit/test_docker_build_context.py index a0637bbc..922819ef 100644 --- a/tests/unit/test_docker_build_context.py +++ b/tests/unit/test_docker_build_context.py @@ -1,6 +1,5 @@ from pathlib import Path - REPO_ROOT = Path(__file__).resolve().parents[2] @@ -12,27 +11,35 @@ def test_backend_docker_context_excludes_generated_and_runtime_state() -> None: } required_patterns = { - "__pycache__", - "*.py[cod]", - ".pytest_cache", - ".mypy_cache", - ".ruff_cache", - ".coverage", - "*.egg-info", - "build", - "dist", + "**/.env", + "**/.env.*", + "**/routstr_secret.key", + "**/.venv", + "**/__pycache__", + "**/*.py[cod]", + "**/.pytest_cache", + "**/.mypy_cache", + "**/.ruff_cache", + "**/.coverage", + "**/htmlcov", + "**/*.egg-info", + "**/build", + "**/dist", "logs", "logs.*", - ".wallet", - ".cashu", - "*.db", - "*.db-*", - "*.sqlite3", - "keys", - "proof_backups", - "relay-data", - "ui", + "**/*.log", + "**/.wallet*", + "**/.cashu", + "**/*.db", + "**/*.db-*", + "**/*.sqlite3", + "**/*.sqlite3-*", + "**/keys", + "**/proof_backups", + "**/relay-data", "ui_out", + "ui/.next", + "ui/out", } assert required_patterns <= patterns, (