diff options
| author | Guillermo Serrahima <dev@vylion.com> | 2026-06-26 14:39:23 +0200 |
|---|---|---|
| committer | Guillermo Serrahima <dev@vylion.com> | 2026-06-26 14:39:23 +0200 |
| commit | 963f59569437fe43a49ce36a003a143fa2f767c8 (patch) | |
| tree | 968b0dad13193536770ae1e6b580b27e22f9366b /docker | |
| parent | 741a04c2abcbd77451c0933a19d91fddb9982882 (diff) | |
| download | senia-963f59569437fe43a49ce36a003a143fa2f767c8.tar.xz senia-963f59569437fe43a49ce36a003a143fa2f767c8.zip | |
created custom agent loop
Diffstat (limited to 'docker')
| -rw-r--r-- | docker/Dockerfile | 62 | ||||
| -rw-r--r-- | docker/compose.yml | 16 |
2 files changed, 55 insertions, 23 deletions
diff --git a/docker/Dockerfile b/docker/Dockerfile index 89f2448..33b44eb 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -2,7 +2,8 @@ FROM debian:trixie-slim ENV DEBIAN_FRONTEND=noninteractive -# core tooling +# ---- System packages ---- + RUN apt-get update && apt-get install -y --no-install-recommends \ sudo \ curl \ @@ -24,44 +25,75 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ iputils-ping \ && rm -rf /var/lib/apt/lists/* -# Narrow sudo: senia can run apt/apt-get only, no password. +# ---- 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 -# the visudo -c validates the file syntax; build fails if it's malformed -# nodejs (for claude code) — using nodesource for a recent version +# ---- 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 -# claude code itself RUN npm install -g @anthropic-ai/claude-code +# ---- Python MCP SDK (system-wide; used by MCP servers, not senia-managed) ---- + RUN pip3 install --break-system-packages mcp -# create non-root user matching common host uid (1000) so mounted volumes have correct ownership +# ---- 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 -# Install uv (the modern python package manager) system-wide so senia can use it -# We install it as senia to avoid root-owned install paths. -RUN curl -LsSf https://astral.sh/uv/install.sh | sh -# uv installs to /home/senia/.local/bin/uv -# Set up npm to install globally into senia's home (no sudo needed) +# 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 -# Make sure her PATH includes the user-local bin dirs -ENV PATH=/home/senia/.local/bin:/home/senia/.npm-global/bin:$PATH +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) ---- + +# 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 -WORKDIR /workspace +# 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 ["bash"] +CMD ["uvicorn", "orchestrator.api:app", "--host", "0.0.0.0"] diff --git a/docker/compose.yml b/docker/compose.yml index 36a02ff..80c0a4d 100644 --- a/docker/compose.yml +++ b/docker/compose.yml @@ -1,17 +1,20 @@ services: senia: build: - context: . - dockerfile: Dockerfile + context: .. + dockerfile: docker/Dockerfile args: USER_UID: 750 USER_GID: 750 image: senia/claude:latest container_name: senia + restart: unless-stopped stdin_open: true tty: true + ports: + - "8000:8000" volumes: - # workspace — read/write, this is where senia does its work + # workspace: read/write, this is where senia does its work - ../workspace:/workspace # claude config and auth: read/write so /login persists @@ -24,15 +27,12 @@ services: # contexts: real if submodule initialized, empty dir otherwise # - ../private/contexts:/etc/senia/data/contexts:ro - # dockerfile read-only — senia can read it, suggest edits in conversation, can't modify + # dockerfile read-only: senia can read it, suggest edits in conversation, can't modify - ./Dockerfile:/etc/senia/Dockerfile:ro # mcp servers source, read-only - ../mcp:/etc/senia/mcp:ro - ../scripts:/etc/senia/scripts - # data dir — read-write, where mcp servers store sqlite dbs and other state + # data dir: read-write, where mcp servers store sqlite dbs and other state - ../data:/etc/senia/data - - working_dir: /workspace - command: tail -f /dev/null |
