FROM debian:bookworm-slim ARG PYTHON_VERSION=3.11 ARG NODE_MAJOR=22 ARG JAVA_VERSION=17 ARG GO_VERSION=1.22.4 ARG GRADLE_VERSION=8.7 ARG TERRAFORM_VERSION=1.8.5 ENV DEBIAN_FRONTEND=noninteractive ENV LANG=C.UTF-8 # Base system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ curl \ wget \ git \ ssh \ make \ build-essential \ unzip \ jq \ gnupg \ lsb-release \ software-properties-common \ libxml2-dev \ libxmlsec1-dev \ libffi-dev \ libpq-dev \ libssl-dev \ zlib1g-dev \ libbz2-dev \ libreadline-dev \ libsqlite3-dev \ zsh \ fd-find \ ripgrep \ && rm -rf /var/lib/apt/lists/* \ && ln -sf /usr/bin/fdfind /usr/local/bin/fd # Set zsh as default shell SHELL ["/bin/zsh", "-c"] RUN chsh -s /bin/zsh root # Python 3.11 via deadsnakes-style build (bookworm ships 3.11) RUN apt-get update && apt-get install -y --no-install-recommends \ python3 \ python3-pip \ python3-venv \ python3-dev \ && ln -sf /usr/bin/python3 /usr/bin/python \ && rm -rf /var/lib/apt/lists/* # Poetry (official installer avoids PyPI timeout issues) ENV POETRY_HOME="/opt/poetry" ENV PATH="${POETRY_HOME}/bin:${PATH}" RUN curl -sSL https://install.python-poetry.org | python3 - && \ poetry config virtualenvs.in-project true # Node.js 22 RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - && \ apt-get install -y --no-install-recommends nodejs && \ rm -rf /var/lib/apt/lists/* # Java 17 (Eclipse Temurin) RUN curl -fsSL https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor -o /usr/share/keyrings/adoptium.gpg && \ echo "deb [signed-by=/usr/share/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb bookworm main" > /etc/apt/sources.list.d/adoptium.list && \ apt-get update && apt-get install -y --no-install-recommends temurin-${JAVA_VERSION}-jdk && \ rm -rf /var/lib/apt/lists/* # Gradle RUN curl -fsSL https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip -o /tmp/gradle.zip && \ unzip -d /opt /tmp/gradle.zip && \ ln -s /opt/gradle-${GRADLE_VERSION}/bin/gradle /usr/local/bin/gradle && \ rm /tmp/gradle.zip # Go RUN ARCH=$(dpkg --print-architecture) && \ curl -fsSL https://go.dev/dl/go${GO_VERSION}.linux-${ARCH}.tar.gz | tar -C /usr/local -xz ENV PATH="/usr/local/go/bin:/root/go/bin:${PATH}" # Docker CLI (client only, expects host docker socket mount) RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker.gpg && \ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable" > /etc/apt/sources.list.d/docker.list && \ apt-get update && apt-get install -y --no-install-recommends docker-ce-cli && \ rm -rf /var/lib/apt/lists/* # kubectl RUN ARCH=$(dpkg --print-architecture) && \ curl -fsSL https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/${ARCH}/kubectl -o /usr/local/bin/kubectl && \ chmod +x /usr/local/bin/kubectl # Helm RUN curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash # AWS CLI v2 RUN ARCH=$(uname -m) && \ curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-${ARCH}.zip" -o /tmp/awscli.zip && \ unzip -q /tmp/awscli.zip -d /tmp && \ /tmp/aws/install && \ rm -rf /tmp/aws /tmp/awscli.zip # Terraform RUN ARCH=$(dpkg --print-architecture) && \ curl -fsSL "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_${ARCH}.zip" -o /tmp/terraform.zip && \ unzip /tmp/terraform.zip -d /usr/local/bin && \ rm /tmp/terraform.zip # Atlassian CLI (acli) RUN mkdir -p -m 755 /etc/apt/keyrings && \ wget -nv -O- https://acli.atlassian.com/gpg/public-key.asc | gpg --dearmor -o /etc/apt/keyrings/acli-archive-keyring.gpg && \ chmod go+r /etc/apt/keyrings/acli-archive-keyring.gpg && \ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/acli-archive-keyring.gpg] https://acli.atlassian.com/linux/deb stable main" > /etc/apt/sources.list.d/acli.list && \ apt-get update && apt-get install -y acli && \ rm -rf /var/lib/apt/lists/* # Rust RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" # Starship prompt RUN curl -sS https://starship.rs/install.sh | sh -s -- -y # Pi coding agent RUN npm install -g @earendil-works/pi-coding-agent # SelimovDE dotfiles RUN git clone https://forge.alexselimov.com/aselimov/SelimovDE.git /root/SelimovDE && \ cd /root/SelimovDE && \ git submodule init && \ git submodule update && \ ./deploy.sh # AWS config (optional, only applied if aws-config exists in build context) COPY Dockerfile aws-config* /tmp/build-context/ RUN if [ -f /tmp/build-context/aws-config ]; then \ mkdir -p /root/.aws && mv /tmp/build-context/aws-config /root/.aws/config; \ fi && rm -rf /tmp/build-context # Pi wrapper script (optional, only applied if bin/pi exists in build context) COPY Dockerfile bin/p* /tmp/build-context/ RUN if [ -f /tmp/build-context/pi ]; then \ mv /tmp/build-context/pi /usr/local/bin/pi && chmod +x /usr/local/bin/pi; \ fi && rm -rf /tmp/build-context # Workspace directory (mount point for ~/repos) RUN mkdir -p /workspace WORKDIR /workspace # Pi state directory lives on a named Docker volume mounted at /root/.pi # (see docker run: -v pi-state:/root/.pi). This keeps pi's hot runtime state # (sessions, logs, caches) on the Linux VM's native ext4 instead of the # macOS bind mount (virtiofs), which is a major perf win for the agent loop. # # Config you want to persist/commit (settings, skills, themes, extensions, # etc.) lives in the workspace at /workspace/dev_sandbox/.pi/agent and is # symlinked into /root/.pi/agent at runtime by entrypoint.sh. RUN mkdir -p /root/.pi # Entrypoint script for runtime auth COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] CMD ["/bin/zsh"]