FROM debian:trixie-slim ENV DEBIAN_FRONTEND=noninteractive # core tooling 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-pip \ python3-venv \ build-essential \ pkg-config \ procps \ iputils-ping \ && rm -rf /var/lib/apt/lists/* # Narrow sudo: senia can run apt/apt-get 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 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 RUN pip3 install --break-system-packages mcp # create non-root user matching common host uid (1000) so mounted volumes have correct ownership 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 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) 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 WORKDIR /workspace CMD ["bash"]