From 840bea1cbaac1f32136399677d7ae8ef06ce532c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ebbe=20Ba=C3=9F?= Date: Thu, 15 Oct 2026 14:58:32 +0200 Subject: [PATCH] fix: gunicorn control socket error and host bytecode in the image Found by running the container on Docker Desktop. Disable gunicorn's control socket (the home directory is read-only) and ignore __pycache__ and .pyc at any depth so host bytecode with the Windows source path stays out of the image. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01Sk72AxLwQnYttF6VFSxQLt --- .dockerignore | 4 ++-- ...ory-project-scaffold-configuration-and-container-plan.md | 6 +++++- docker/entrypoint.sh | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.dockerignore b/.dockerignore index cd33877..022597f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,8 @@ .git .gitignore .venv -__pycache__ -*.pyc +**/__pycache__ +**/*.pyc .pytest_cache .ruff_cache .env diff --git a/_bmad-output/initiative-ping-mee-portal/epic-platform-and-sign-in/story-project-scaffold-configuration-and-container-plan.md b/_bmad-output/initiative-ping-mee-portal/epic-platform-and-sign-in/story-project-scaffold-configuration-and-container-plan.md index b463cb0..bc1676d 100644 --- a/_bmad-output/initiative-ping-mee-portal/epic-platform-and-sign-in/story-project-scaffold-configuration-and-container-plan.md +++ b/_bmad-output/initiative-ping-mee-portal/epic-platform-and-sign-in/story-project-scaffold-configuration-and-container-plan.md @@ -80,7 +80,9 @@ Greenfield: only planning documents exist. New files, using the spine's source t - `README.md` was rewritten and no longer carries the original project name line. - Ruff excludes `_bmad`, `_bmad-output`, `.agents` and `context-resources`. - The 503 criterion is tested with a mocked unreachable database, not an unreadable file. -- Not verified: the Docker build, the read-only root file system with gunicorn's worker temp dir, the `uv` image tag and the container health check. They need `docker compose up --build` on the Linux host. +- Docker was verified on the development machine afterwards (Docker Desktop 29.8.2, Linux engine): the image builds, the container is healthy, runs as uid 10001, has a read-only root file system with `/data`, `/backups` and `/tmp` writable, answers `/healthz` with 200 and all security headers, returns 400 with the CSP for an unlisted Host, keeps the database across a restart, exits 1 on invalid configuration naming every bad variable, and logs no query strings. +- The live test found two defects the unit tests could not: gunicorn 26 logged a startup error because its control socket could not be created in the read-only home directory (fixed with `--no-control-socket`), and host `__pycache__` files, which embed the Windows source path, were copied into the image because `.dockerignore` only matched the top-level folder (fixed with `**/__pycache__` and `**/*.pyc`). The image no longer contains the project name. +- Still to confirm on the Linux host: the same checks behind Zoraxy, and that the uv image tag builds there. - `compose.yaml` publishes port 8000 on all host interfaces. Bind it to a specific address if the reverse proxy runs on the same host. - Resolved versions in `uv.lock`: Django 5.2.18, gunicorn 26.2.0, whitenoise 6.12.0. @@ -100,6 +102,8 @@ Pass 1 (quick lens). Counts: high 1, medium 3, low 3, false 1, maybe-false 0. | 6 | Gunicorn error log is plain text on stderr | low | rejected | Server start and error lines only; app logs are JSON. A JSON gunicorn log config is more than a direct correction. | | 7 | "No ping-mee name" not satisfiable because of the plan file | false | rejected | The criterion covers code and image; `.dockerignore` excludes `_bmad-output` and a search outside protected folders found nothing. | | 8 | 503 criterion tested with a mock, not an unreadable file | low | rejected | Disclosed in Implementation Notes; the view returns 503 on any exception from `cursor()`, so a real failure cannot return 200. A real-file test needs database wrapper plumbing. | +| 9 | Gunicorn startup error: control socket cannot be created (found in the live container test) | medium | patch | `[ERROR] Control server error: [Errno 30] Read-only file system: '/home/app'` at every start; fixed with `--no-control-socket`, error gone. | +| 10 | Host `__pycache__` copied into the image, embedding the Windows source path (found in the live container test) | medium | patch | `grep` in the image found the project name in `.pyc` files; `.dockerignore` matched only the top-level folder; fixed with `**/` patterns, rescan is clean. | ## Design Notes diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 54553ab..2a37191 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -9,4 +9,5 @@ exec gunicorn portal.config.wsgi:application \ --threads 4 \ --preload \ --worker-tmp-dir /tmp \ - --error-logfile - + --error-logfile - \ + --no-control-socket