# Nix-built shower app container — Adelaide / Heidi / Addie baby shower. # # The app is published as a wheel to the Forgejo PyPI index at # https://forge.eblu.me/api/packages/eblume/pypi/. The wheel + its # Python deps are baked in at build time via buildPythonPackage so the # container boots cleanly with no pip-at-runtime. Build runs on the # nix-container-builder runner (ringtail, amd64) so the image is native. # # To bump the version: # 1. Update `version` below. # 2. Update `wheelHash` — `nix-prefetch-url ` against the new wheel, # or set it to `pkgs.lib.fakeHash` and let the build print the right one. { pkgs ? import { } }: let version = "1.0.0"; wheelHash = "sha256-9Xk3TCzl474As8n0RhLoy/QYw+K1DABBWEwLC8v1X0A="; python = pkgs.python314; showerWheel = pkgs.fetchurl { name = "adelaide_baby_shower_app-${version}-py3-none-any.whl"; url = "https://forge.eblu.me/api/packages/eblume/pypi/files/adelaide-baby-shower-app/${version}/adelaide_baby_shower_app-${version}-py3-none-any.whl"; hash = wheelHash; }; shower = python.pkgs.buildPythonPackage { pname = "adelaide-baby-shower-app"; inherit version; format = "wheel"; src = showerWheel; doCheck = false; propagatedBuildInputs = with python.pkgs; [ django django-axes pillow scipy segno ]; }; pyEnv = python.withPackages (ps: [ shower ps.gunicorn ]); # Settings shim — config/settings.py's `BASE_DIR = parent.parent` would # otherwise resolve to site-packages, scattering db.sqlite3 / media / # staticfiles into the venv. Pin them to /app/{data,media,data/static}. localSettings = pkgs.writeText "local_settings.py" '' from config.settings import * # noqa: F401,F403 DATABASES["default"]["NAME"] = "/app/data/db.sqlite3" MEDIA_ROOT = "/app/media" STATIC_ROOT = "/app/data/staticfiles" ''; entrypoint = pkgs.writeShellScript "shower-entrypoint" '' set -eu export HOME=/app/data export PYTHONPATH=/app export DJANGO_SETTINGS_MODULE=local_settings cd /app mkdir -p /app/data /app/media echo "shower: running migrations" ${pyEnv}/bin/python -m django migrate --noinput echo "shower: collecting static files" ${pyEnv}/bin/python -m django collectstatic --noinput --clear echo "shower: starting gunicorn" exec ${pyEnv}/bin/gunicorn \ --bind 0.0.0.0:8000 \ --workers 2 \ --forwarded-allow-ips='*' \ config.wsgi:application ''; in pkgs.dockerTools.buildLayeredImage { name = "blumeops/shower"; contents = [ pyEnv pkgs.cacert pkgs.tzdata pkgs.bashInteractive pkgs.coreutils ]; extraCommands = '' mkdir -p app/data app/media tmp chmod 1777 tmp cp ${localSettings} app/local_settings.py ''; fakeRootCommands = '' chown -R 1000:1000 app ''; enableFakechroot = true; config = { Entrypoint = [ "${entrypoint}" ]; Env = [ "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" "TZDIR=${pkgs.tzdata}/share/zoneinfo" "TZ=America/Los_Angeles" "TMPDIR=/tmp" "LANG=C.UTF-8" "LC_ALL=C.UTF-8" ]; ExposedPorts = { "8000/tcp" = { }; }; User = "1000"; WorkingDir = "/app"; }; }