FROM python:3.11-slim AS runtime ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 WORKDIR /app # Dependencies first: this layer is cached and only rebuilt when # requirements.txt changes, not on every code change. COPY expenses_manager/requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Copy the Django project itself, not the repository root, so /app is the # directory holding manage.py. COPY expenses_manager/ . # Collect static files at build time so the running container never needs to # write to its own filesystem. SECRET_KEY is required by settings.py when # DEBUG is False but collectstatic never uses it, so a throwaway value is # enough — the real one comes from the environment at runtime. RUN SECRET_KEY=build-time-placeholder \ DEBUG=False \ ALLOWED_HOSTS=localhost \ python manage.py collectstatic --noinput EXPOSE 8000 CMD ["gunicorn", "expenses_manager.wsgi:application", "--bind", "0.0.0.0:8000"] # The production image plus the test-only dependencies. Tests then run on # exactly the Python version and packages production uses; the virtualenv this # replaces ran on Python 3.14 while production runs 3.11. FROM runtime AS test RUN pip install --no-cache-dir -r requirements-dev.txt