C1: bake shower runtime env into image; allow tailnet host
Two complementary fixes for the deploy that just landed: 1. Pod was 0/1 Running because the readiness probe sends `Host: shower.ops.eblu.me` and the app's hardcoded ALLOWED_HOSTS only includes `shower.eblu.me`. settings.py exposes a DJANGO_ALLOWED_HOSTS env-var extras hook for exactly this case — wired into the configmap. 2. `kubectl exec deploy/shower -- python -m django <cmd>` returned "No module named django" because PYTHONPATH lived only inside the entrypoint script. Moved PYTHONPATH, DJANGO_SETTINGS_MODULE, PATH, and HOME into the image's Env block so exec'd shells inherit them. The entrypoint now just runs the boot sequence; the exports are redundant (image Env covers them) and gone. FOD inputs are unchanged so outputHash stays valid; no fakeHash dance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6d3cce5626
commit
95b663209f
2 changed files with 20 additions and 8 deletions
|
|
@ -5,6 +5,12 @@ metadata:
|
||||||
namespace: shower
|
namespace: shower
|
||||||
data:
|
data:
|
||||||
DJANGO_DEBUG: "0"
|
DJANGO_DEBUG: "0"
|
||||||
|
# The app's settings.py hardcodes ALLOWED_HOSTS = ["shower.eblu.me",
|
||||||
|
# "localhost", "127.0.0.1"] and exposes this env var as a comma-separated
|
||||||
|
# extras list. shower.ops.eblu.me is what Caddy on indri and the
|
||||||
|
# Tailscale ProxyGroup both send as the Host header, so the app needs to
|
||||||
|
# accept it.
|
||||||
|
DJANGO_ALLOWED_HOSTS: "shower.ops.eblu.me"
|
||||||
# /host/, /admin/, and Django's login surface are all tailnet-only — the
|
# /host/, /admin/, and Django's login surface are all tailnet-only — the
|
||||||
# public proxy 403s everything outside of `/` and `/prizes/<token>/`.
|
# public proxy 403s everything outside of `/` and `/prizes/<token>/`.
|
||||||
# /host/'s "Django admin" link follows DJANGO_ADMIN_URL.
|
# /host/'s "Django admin" link follows DJANGO_ADMIN_URL.
|
||||||
|
|
|
||||||
|
|
@ -154,26 +154,25 @@ let
|
||||||
STATIC_ROOT = "/app/data/staticfiles"
|
STATIC_ROOT = "/app/data/staticfiles"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# PYTHONPATH, DJANGO_SETTINGS_MODULE, PATH, and HOME live in the image's
|
||||||
|
# `Env` block below — that way `kubectl exec deploy/shower -- python -m
|
||||||
|
# django <subcommand>` Just Works without an inline `env` ceremony.
|
||||||
|
# The entrypoint just changes directory and runs the boot sequence.
|
||||||
entrypoint = pkgs.writeShellScript "shower-entrypoint" ''
|
entrypoint = pkgs.writeShellScript "shower-entrypoint" ''
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
export HOME=/app/data
|
|
||||||
export PATH=${pyDeps}/bin:${python}/bin:/bin
|
|
||||||
export PYTHONPATH=/app:${sitePackages}
|
|
||||||
export DJANGO_SETTINGS_MODULE=local_settings
|
|
||||||
|
|
||||||
cd /app
|
cd /app
|
||||||
|
|
||||||
mkdir -p /app/data /app/media
|
mkdir -p /app/data /app/media
|
||||||
|
|
||||||
echo "shower: running migrations"
|
echo "shower: running migrations"
|
||||||
${python}/bin/python -m django migrate --noinput
|
python -m django migrate --noinput
|
||||||
|
|
||||||
echo "shower: collecting static files"
|
echo "shower: collecting static files"
|
||||||
${python}/bin/python -m django collectstatic --noinput --clear
|
python -m django collectstatic --noinput --clear
|
||||||
|
|
||||||
echo "shower: starting gunicorn"
|
echo "shower: starting gunicorn"
|
||||||
exec ${pyDeps}/bin/gunicorn \
|
exec gunicorn \
|
||||||
--bind 0.0.0.0:8000 \
|
--bind 0.0.0.0:8000 \
|
||||||
--workers 2 \
|
--workers 2 \
|
||||||
--forwarded-allow-ips='*' \
|
--forwarded-allow-ips='*' \
|
||||||
|
|
@ -213,6 +212,13 @@ pkgs.dockerTools.buildLayeredImage {
|
||||||
"LANG=C.UTF-8"
|
"LANG=C.UTF-8"
|
||||||
"LC_ALL=C.UTF-8"
|
"LC_ALL=C.UTF-8"
|
||||||
"PYTHONDONTWRITEBYTECODE=1"
|
"PYTHONDONTWRITEBYTECODE=1"
|
||||||
|
"HOME=/app/data"
|
||||||
|
"PATH=${pyDeps}/bin:${python}/bin:/bin"
|
||||||
|
# /app first so local_settings.py is importable; sitePackages second so
|
||||||
|
# django, gunicorn, etc. resolve. Inherited by entrypoint + any
|
||||||
|
# `kubectl exec` so manual django subcommands work without ceremony.
|
||||||
|
"PYTHONPATH=/app:${sitePackages}"
|
||||||
|
"DJANGO_SETTINGS_MODULE=local_settings"
|
||||||
];
|
];
|
||||||
ExposedPorts = {
|
ExposedPorts = {
|
||||||
"8000/tcp" = { };
|
"8000/tcp" = { };
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue