# Dockerfile # Use a Python image with uv pre-installed FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim # Setup a non-root user RUN groupadd --system --gid 999 nonroot \ && useradd --system --gid 999 --uid 999 --create-home nonroot # Set environment variables ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 ENV DJANGO_SETTINGS_MODULE=dashboard_project.settings # Change the working directory to the `app` directory WORKDIR /app # Enable bytecode compilation ENV UV_COMPILE_BYTECODE=1 # Copy from the cache instead of linking since it's a mounted volume ENV UV_LINK_MODE=copy # Install dependencies (separate layer for caching) RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ uv sync --frozen --no-install-project --no-dev # Copy the project into the image COPY . /app # Sync the project (install the project itself) RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-dev # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" # Change to the Django project directory WORKDIR /app/dashboard_project # Collect static files (runs as root) RUN uv run manage.py collectstatic --noinput # Fix ownership of dashboard_project directory for nonroot user # This ensures db.sqlite3 and any files created during runtime are writable RUN chown -R nonroot:nonroot /app/dashboard_project && \ chmod 775 /app/dashboard_project # Change back to the app directory WORKDIR /app # Use the non-root user to run our application USER nonroot # Run gunicorn via uv run to ensure it's in the environment CMD ["uv", "run", "gunicorn", "dashboard_project.wsgi:application", "--bind", "0.0.0.0:8000", "--chdir", "dashboard_project"]