2026-05-13 20:51:24 -04:00
|
|
|
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
|
2026-05-26 09:51:57 -04:00
|
|
|
ARG ZIG_VERSION=0.16.0
|
2026-05-13 20:51:24 -04:00
|
|
|
|
|
|
|
|
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 \
|
2026-05-26 10:30:21 -04:00
|
|
|
liblzma-dev \
|
2026-05-13 20:51:24 -04:00
|
|
|
libreadline-dev \
|
|
|
|
|
libsqlite3-dev \
|
2026-05-26 10:30:21 -04:00
|
|
|
libncursesw5-dev \
|
|
|
|
|
xz-utils \
|
|
|
|
|
uuid-dev \
|
2026-05-13 20:51:24 -04:00
|
|
|
zsh \
|
|
|
|
|
fd-find \
|
|
|
|
|
ripgrep \
|
2026-05-14 19:13:04 -04:00
|
|
|
neovim \
|
|
|
|
|
less \
|
2026-05-26 09:51:57 -04:00
|
|
|
hugo \
|
|
|
|
|
xz-utils \
|
2026-05-13 20:51:24 -04:00
|
|
|
&& 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
|
|
|
|
|
|
2026-05-14 19:13:04 -04:00
|
|
|
# uv (fast Python package/project manager from Astral)
|
|
|
|
|
RUN curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR=/usr/local/bin sh
|
|
|
|
|
|
2026-05-26 09:51:57 -04:00
|
|
|
# Keep sandbox-created Python project virtualenvs separate from the host/user .venv.
|
|
|
|
|
# This avoids invalid interpreter symlinks when the same workspace is shared with macOS.
|
|
|
|
|
ENV UV_PROJECT_ENVIRONMENT=".venv_sandbox"
|
|
|
|
|
|
2026-05-13 20:51:24 -04:00
|
|
|
# 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
|
|
|
|
|
|
2026-05-26 10:30:21 -04:00
|
|
|
|
|
|
|
|
# yq (mikefarah)
|
|
|
|
|
ARG YQ_VERSION=v4.44.3
|
|
|
|
|
RUN ARCH=$(dpkg --print-architecture) && \
|
|
|
|
|
curl -fsSL "https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${ARCH}" -o /usr/local/bin/yq && \
|
|
|
|
|
chmod +x /usr/local/bin/yq
|
|
|
|
|
|
2026-05-13 20:51:24 -04:00
|
|
|
# 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
|
|
|
|
|
|
2026-05-26 09:51:57 -04:00
|
|
|
# Zig
|
|
|
|
|
RUN ARCH=$(uname -m) && \
|
|
|
|
|
case "$ARCH" in \
|
|
|
|
|
x86_64) ZIG_ARCH=x86_64 ;; \
|
|
|
|
|
aarch64) ZIG_ARCH=aarch64 ;; \
|
|
|
|
|
*) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \
|
|
|
|
|
esac && \
|
|
|
|
|
curl -fsSL "https://ziglang.org/download/${ZIG_VERSION}/zig-${ZIG_ARCH}-linux-${ZIG_VERSION}.tar.xz" -o /tmp/zig.tar.xz && \
|
|
|
|
|
tar -C /opt -xf /tmp/zig.tar.xz && \
|
|
|
|
|
mv "/opt/zig-${ZIG_ARCH}-linux-${ZIG_VERSION}" "/opt/zig-${ZIG_VERSION}" && \
|
|
|
|
|
ln -s "/opt/zig-${ZIG_VERSION}/zig" /usr/local/bin/zig && \
|
|
|
|
|
rm /tmp/zig.tar.xz
|
|
|
|
|
|
2026-05-13 20:51:24 -04:00
|
|
|
# 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/*
|
|
|
|
|
|
2026-05-26 10:30:21 -04:00
|
|
|
# GitHub CLI (gh)
|
|
|
|
|
RUN mkdir -p -m 755 /etc/apt/keyrings && \
|
|
|
|
|
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | gpg --dearmor -o /etc/apt/keyrings/githubcli-archive-keyring.gpg && \
|
|
|
|
|
chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg && \
|
|
|
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list && \
|
|
|
|
|
apt-get update && apt-get install -y gh && \
|
|
|
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
|
|
2026-05-13 20:51:24 -04:00
|
|
|
# Rust
|
|
|
|
|
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
|
|
|
|
ENV PATH="/root/.cargo/bin:${PATH}"
|
|
|
|
|
|
2026-05-14 19:13:04 -04:00
|
|
|
# Jujutsu (jj) - Git-compatible VCS
|
|
|
|
|
RUN cargo install --locked jj-cli
|
|
|
|
|
|
2026-05-13 20:51:24 -04:00
|
|
|
# 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
|
|
|
|
|
|
2026-05-26 10:30:21 -04:00
|
|
|
# Global gitignore: lives on the host at ~/repos/dev_sandbox/.gitignore_global
|
|
|
|
|
# (bind-mounted to /workspace/dev_sandbox/.gitignore_global). Symlinked into
|
|
|
|
|
# place by entrypoint.sh so host edits take effect without a rebuild.
|
|
|
|
|
RUN git config --system core.excludesfile /root/.gitignore_global
|
|
|
|
|
|
2026-05-13 20:51:24 -04:00
|
|
|
# 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"]
|