agent-container/Dockerfile
Jeena e91b74ea38 tools: Install on first use instead of baking them into the image
Baked installs had two failure modes: anything installed into $HOME
at build time is shadowed by the container-home bind mount at runtime,
and system-wide installs are root-owned, so the tools' own update
commands (pi update, claude update, opencode upgrade) failed with an
unwritable install path. With pi releasing new versions almost daily,
the only remedy, a full image rebuild that also deleted every
container, was too heavy for that cadence.

Now each tool is installed at runtime into the persistent container
home by its official installer (no sudo), the same way the Docker
image itself is built on first use. Self-updates work inside the
container and survive image rebuilds and container recreation. The
image shrinks to a plain Arch base, and agent-container update no
longer removes containers, so sudo-installed project dependencies
survive it too.

docker exec now attaches a TTY only when stdin is one, so scripted
runs like 'pi -p' work without a terminal.
2026-09-18 08:38:23 +09:00

33 lines
1 KiB
Docker

FROM archlinux:latest
ARG USERNAME=dev
ARG UID=1000
ARG GID=1000
RUN pacman -Syu --noconfirm \
base-devel \
git \
ca-certificates \
bash \
less \
ripgrep \
nodejs \
npm \
curl \
sudo && \
groupadd -g ${GID} ${USERNAME} && \
useradd -m -u ${UID} -g ${GID} -s /bin/bash ${USERNAME} && \
echo "${USERNAME} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
pacman -Scc --noconfirm
# OpenCode, Claude Code, and Pi are intentionally NOT baked into the image:
# an install into $HOME at build time would be shadowed by the container-home
# bind mount, and system-wide installs are root-owned and not self-updatable.
# On first use, agent-container.py runs each tool's official installer (no
# sudo) against the persistent container home instead, so `pi update`,
# `claude update`, and `opencode upgrade` work inside the container and
# survive image rebuilds and container recreation. See _bootstrap_tool() in
# agent-container.py.
USER ${USERNAME}
WORKDIR /home/${USERNAME}