Keep secrets and runtime data out of the Docker images

The build context is the repository root and there was no .dockerignore, so
'COPY backend/ ./' swept backend/venv (327 MB), backend/media (the actual
library, 224 MB), backend/logs, backend/staticfiles and backend/.env
(SECRET_KEY plus the database password) into the backend image: 1.43 GB per
architecture, including secrets headed for the registry. The frontend build
stage also copied the host's node_modules over the fresh install.

- Root .dockerignore excludes .git, virtualenvs, __pycache__, db.sqlite3,
  logs/staticfiles, .env files, media/, node_modules, dist and the deploy
  runtime state (data/, tailscale-state/).
- The backend Dockerfile now asserts the context is clean (.env, venv,
  media/library, db.sqlite3 all absent) before collectstatic, so a missing
  ignore file fails the build instead of leaking.
- Rebuilt: backend 1.43 GB -> 876 MB ('COPY backend/' is now 268 kB),
  frontend stays at 65 MB. Verified by booting the compose stack with the
  new image: migrations applied, /health ok, no .env or venv inside, and
  /app/media is the mounted (empty) volume; the scheduler runs too.
- Removed the stale local images that still contained the library and the
  dev .env.
This commit is contained in:
2026-09-18 16:04:55 -05:00
parent 1170e6e9c1
commit a17dd5a4ef
3 changed files with 52 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
# Build context is the repository root (see deploy/J621-Backend and
# deploy/J621-Frontend). Keep the context small and, more importantly, keep
# secrets and runtime data out of the images.
# Version control / tooling
.git
.gitignore
.dockerignore
# Python: the dev virtualenv, caches, and anything generated at runtime
backend/venv/
**/__pycache__/
**/*.py[cod]
backend/db.sqlite3
backend/logs/
backend/staticfiles/
# Secrets and media: the .env holds SECRET_KEY and DB passwords, media/ is
# the actual library. The deploy composes mount these at runtime instead.
backend/.env
backend/.env.*
backend/media/
# Frontend build artefacts (npm ci installs fresh from the lockfile)
frontend/node_modules/
frontend/dist/
# Deploy runtime state and env
deploy/.env
deploy/.env.*
deploy/data/
deploy/tailscale-state/
# Misc
*.log
+8
View File
@@ -30,6 +30,14 @@ COPY backend/ ./
COPY deploy/backend-entrypoint.sh /usr/local/bin/j621-entrypoint COPY deploy/backend-entrypoint.sh /usr/local/bin/j621-entrypoint
COPY deploy/scheduler-entrypoint.sh /usr/local/bin/j621-scheduler COPY deploy/scheduler-entrypoint.sh /usr/local/bin/j621-scheduler
# Guard: fail the build if the context leaked secrets or runtime data
# (.dockerignore excludes them — see the repository root).
RUN test ! -e /app/.env \
&& test ! -d /app/venv \
&& test ! -d /app/media/library \
&& test ! -e /app/db.sqlite3 \
&& echo "build context clean"
RUN chmod +x /usr/local/bin/j621-entrypoint /usr/local/bin/j621-scheduler \ RUN chmod +x /usr/local/bin/j621-entrypoint /usr/local/bin/j621-scheduler \
&& mkdir -p /app/media /app/logs \ && mkdir -p /app/media /app/logs \
&& python manage.py collectstatic --noinput && python manage.py collectstatic --noinput
+9
View File
@@ -114,6 +114,15 @@ ffmpeg for video thumbnails. The `GIT_HASH` build arg is baked into the
backend image so the shell's version pill shows the commit (images have no backend image so the shell's version pill shows the commit (images have no
`.git` directory); the push scripts pass it automatically. `.git` directory); the push scripts pass it automatically.
Both build from the repository root, which is filtered by `.dockerignore`:
`backend/venv`, `backend/media`, `backend/logs`, `backend/staticfiles`,
`backend/.env`, `frontend/node_modules`, `frontend/dist` and the deploy
runtime state never enter the images — the database, media and logs come
from the compose volumes and `deploy/.env` at runtime. The backend build
also asserts that (`.env`, `venv`, `media/library`, `db.sqlite3` absent), so
a missing ignore file fails the build instead of shipping secrets. Rebuild
(and `docker image prune`) if you built before that guard existed.
Push multi-arch images to the Gitea registry: Push multi-arch images to the Gitea registry:
```bash ```bash