FROM python:3.14-slim # Copy uv helper binary from the uv image so we can manage venvs and pip COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 # Install build deps required for common Python packages and netcat for health wait RUN apt-get update \ && apt-get install -y --no-install-recommends \ build-essential \ gcc \ git \ libpq-dev \ pkg-config \ libcairo2-dev \ # some distributions provide libgdk-pixbuf under the xlib name libgdk-pixbuf-xlib-2.0-0 \ libgdk-pixbuf-xlib-2.0-dev \ libjpeg-dev \ zlib1g-dev \ wget \ ca-certificates \ netcat-openbsd \ && rm -rf /var/lib/apt/lists/* WORKDIR /usr/src/app # Install python deps into a uv-managed venv for reproducible builds COPY requirements.txt /usr/src/app/ # Prebuild wheels into /wheels so compiled artifacts are cached in a layer. # This speeds rebuilds when `requirements.txt` hasn't changed. The first build # still needs to compile any packages without prebuilt wheels. RUN mkdir -p /wheels \ && python -m venv /tmp/venvbuild \ && /tmp/venvbuild/bin/pip install --upgrade pip setuptools wheel \ && /tmp/venvbuild/bin/pip wheel --wheel-dir=/wheels -r requirements.txt \ && rm -rf /tmp/venvbuild # Create the final uv-managed venv and install from the cached wheels where # possible. Using `--no-index --find-links=/wheels` makes pip prefer the # prebuilt wheels, avoiding recompilation. RUN uv venv /opt/venv \ && export VIRTUAL_ENV=/opt/venv \ && export PATH="/opt/venv/bin:$PATH" \ && uv pip install --upgrade pip setuptools wheel \ && uv pip install --no-index --find-links=/wheels -r requirements.txt # Ensure the runtime environment uses the uv-managed venv by default. # This persists the venv into image ENV so `python` and `gunicorn` point # to the venv-installed binaries at container start. ENV VIRTUAL_ENV=/opt/venv ENV PATH="/opt/venv/bin:$PATH" # Create non-root user before copying files so we can use Docker's # `--chown` flag during COPY and avoid an expensive recursive `chown -R`. RUN useradd -m appuser # Create directory for application logs and ensure ownership is correct. # Do this as root before switching to `appuser` so the directory exists # and can be mounted by the dev compose override. RUN mkdir -p /var/log/rad \ && chown -R appuser:appuser /var/log/rad # Copy project files into image and set ownership during copy (faster than # a separate `chown -R` step). This keeps layer reuse efficient. COPY --chown=appuser:appuser . /usr/src/app # Ensure the venv is usable by the non-root user; chown only the venv path # (much smaller than the whole project tree) to avoid a long recursive chown. RUN chown -R appuser:appuser /opt/venv # Make the entrypoint executable (some files in the repo may not have the # executable bit set). Do this as root before switching to the app user. RUN [ -f /usr/src/app/entrypoint.sh ] && chmod +x /usr/src/app/entrypoint.sh || true USER appuser ENTRYPOINT ["/usr/src/app/entrypoint.sh"]