FROM debian:trixie-slim ENV DEBIAN_FRONTEND=noninteractive # ---- System packages ---- RUN apt-get update && apt-get install -y --no-install-recommends \ sudo \ curl \ wget \ git \ ca-certificates \ gnupg \ jq \ ripgrep \ less \ vim \ sqlite3 \ python3 \ python3-dev \ python3-pip \ python3-venv \ build-essential \ pkg-config \ procps \ iputils-ping \ tzdata \ && rm -rf /var/lib/apt/lists/* # ---- timezone ---- ENV TZ=Europe/Madrid RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime \ && echo $TZ > /etc/timezone # ---- Narrow sudo for senia (apt only, no password) ---- RUN echo "senia ALL=(root) NOPASSWD: /usr/bin/apt, /usr/bin/apt-get" \ > /etc/sudoers.d/senia-apt \ && chmod 440 /etc/sudoers.d/senia-apt \ && visudo -c -f /etc/sudoers.d/senia-apt # ---- Node + claude code ---- RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ && apt-get install -y --no-install-recommends nodejs \ && rm -rf /var/lib/apt/lists/* RUN npm install -g npm@11.14.0 RUN npm install -g @anthropic-ai/claude-code # ---- Non-root user ---- ARG USER_UID=750 ARG USER_GID=750 RUN groupadd --system --gid ${USER_GID} senia \ && useradd --system --uid ${USER_UID} --gid ${USER_GID} -m -s /bin/bash senia \ && echo "umask 002" >> /home/senia/.bashrc # ---- uv (the python project manager for the agent loop) ---- # Single static binary, no python deps. The official image is the canonical install path. COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv # uv config: # - put venvs in a known location, not next to pyproject.toml # - compile bytecode at install time for faster startup # - copy instead of hardlink for predictable docker layer behavior ENV UV_PROJECT_ENVIRONMENT=/opt/venv \ UV_COMPILE_BYTECODE=1 \ UV_LINK_MODE=copy # ---- User-level tools for senia (claude code, npm prefix) ---- USER senia # Set up npm prefix for any *other* user-level node tools senia might want RUN mkdir -p /home/senia/.npm-global \ && npm config set prefix /home/senia/.npm-global USER root # senia's PATH includes her user-local npm bins + the venv that uv populates ENV PATH="/opt/venv/bin:/home/senia/.npm-global/bin:$PATH" # ---- Agent project install (with layer caching) ---- # python-olm stuff; waiting for matrix-nio to deprecate the dependency ENV CMAKE_POLICY_VERSION_MINIMUM=3.5 # Deps first; cached as long as pyproject.toml + uv.lock are unchanged COPY --chown=senia:senia agent/pyproject.toml agent/uv.lock /etc/senia/agent/ WORKDIR /etc/senia/agent RUN uv sync --frozen --no-install-project --no-dev # Then the project code COPY --chown=senia:senia agent/ /etc/senia/agent/ RUN uv sync --frozen --no-dev # ---- Runtime ---- USER senia # WORKDIR /etc/senia/agent EXPOSE 8000 CMD ["uvicorn", "orchestrator.api:app", "--host", "0.0.0.0"]