mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-11-13 09:13:30 +01:00
76 lines
2.6 KiB
Docker
76 lines
2.6 KiB
Docker
# ai/Dockerfile
|
|||
|
|
# AI development sandbox for AkkudoktorEOS.
|
||
|
|
# Runs as a non-root user whose UID/GID match the host to keep bind-mount ownership sane.
|
||
|
|
|
||
|
|
# uv comes from its official image. BuildKit does not expand variables in
|
||
|
|
# `COPY --from`, so the image is a named stage with a global ARG. Keep
|
||
|
|
# UV_VERSION in sync with .github/workflows/pre-commit.yml.
|
||
|
|
ARG UV_VERSION=0.12.9
|
||
|
|
FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv
|
||
|
|
|
||
|
|
FROM debian:bookworm-slim
|
||
|
|
|
||
|
|
ARG UID=1000
|
||
|
|
ARG GID=1000
|
||
|
|
ARG USERNAME=dev
|
||
|
|
|
||
|
|
# Pinned tool versions (UV_VERSION is above). Bump them and rebuild
|
||
|
|
# (AI_SANDBOX_REBUILD=1) to update.
|
||
|
|
ARG CLAUDE_CODE_VERSION=2.1.319
|
||
|
|
ARG OPENCODE_VERSION=1.19.5
|
||
|
|
ARG QWEN_CODE_VERSION=0.27.0
|
||
|
|
|
||
|
|
ENV DEBIAN_FRONTEND=noninteractive \
|
||
|
|
PYTHONUNBUFFERED=1 \
|
||
|
|
UV_LINK_MODE=copy \
|
||
|
|
PATH="/home/${USERNAME}/.local/bin:${PATH}"
|
||
|
|
|
||
|
|
# Base tooling: git, GitHub CLI and build tools. No sudo: the agent must not
|
||
|
|
# be able to become root, even if no-new-privileges were removed.
|
||
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||
|
|
ca-certificates \
|
||
|
|
curl \
|
||
|
|
git \
|
||
|
|
gh \
|
||
|
|
gnupg \
|
||
|
|
build-essential \
|
||
|
|
&& rm -rf /var/lib/apt/lists/*
|
||
|
|
|
||
|
|
# Copy the uv binary from the uv stage.
|
||
|
|
COPY --from=uv /uv /uvx /bin/
|
||
|
|
|
||
|
|
# Install Python 3.13 outside /root (mode 0700, unreachable for the dev user)
|
||
|
|
# and link it into /usr/local/bin, where uv finds it as an interpreter on PATH.
|
||
|
|
RUN UV_PYTHON_INSTALL_DIR=/opt/uv-python UV_PYTHON_BIN_DIR=/usr/local/bin \
|
||
|
|
uv python install 3.13 \
|
||
|
|
&& chmod -R a+rX /opt/uv-python \
|
||
|
|
&& /usr/local/bin/python3.13 --version
|
||
|
|
|
||
|
|
# Install Node.js 22.x (needed for the AI CLIs).
|
||
|
|
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
||
|
|
&& apt-get install -y --no-install-recommends nodejs \
|
||
|
|
&& rm -rf /var/lib/apt/lists/*
|
||
|
|
|
||
|
|
# AI CLIs as global npm packages (installed under /usr, readable for everyone).
|
||
|
|
RUN npm install -g \
|
||
|
|
"@anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}" \
|
||
|
|
"opencode-ai@${OPENCODE_VERSION}" \
|
||
|
|
"@qwen-code/qwen-code@${QWEN_CODE_VERSION}" \
|
||
|
|
&& npm cache clean --force
|
||
|
|
|
||
|
|
# Create a non-root user matching the host UID/GID.
|
||
|
|
RUN groupadd -g ${GID} ${USERNAME} 2>/dev/null || true \
|
||
|
|
&& useradd -m -u ${UID} -g ${GID} -s /bin/bash ${USERNAME}
|
||
|
|
|
||
|
|
# Install the entrypoint into the read-only image layer, owned by root.
|
||
|
|
# It must NOT live under /home/dev: that path is the persistent `ai-home`
|
||
|
|
# volume, so a copy there would be shadowed by a stale file from the volume
|
||
|
|
# and would be writable by the agent.
|
||
|
|
COPY --chown=root:root --chmod=0755 entrypoint.sh /usr/local/bin/entrypoint.sh
|
||
|
|
|
||
|
|
USER ${USERNAME}
|
||
|
|
WORKDIR /workspace
|
||
|
|
|
||
|
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||
|
|
CMD ["bash"]
|