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.
This commit is contained in:
Jeena 2026-09-18 08:38:23 +09:00
parent 70699026c3
commit e91b74ea38
3 changed files with 140 additions and 43 deletions

View file

@ -20,27 +20,14 @@ RUN pacman -Syu --noconfirm \
echo "${USERNAME} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
pacman -Scc --noconfirm
# Install OpenCode from AUR
WORKDIR /tmp
# 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}
RUN git clone https://aur.archlinux.org/opencode-bin.git && \
cd opencode-bin && \
makepkg --syncdeps --noconfirm --install && \
sudo rm -rf /tmp/opencode-bin && \
sudo pacman -Scc --noconfirm
# Install Claude Code using the native installer, then copy the binary
# to a system-wide location so it survives the home directory bind mount
RUN curl -fsSL https://claude.ai/install.sh | bash && \
sudo cp ~/.local/bin/claude /usr/local/bin/claude && \
rm -rf ~/.local/share/claude ~/.local/bin/claude ~/.claude ~/.claude.json \
~/.cache/claude
# Install Pi Coding Agent globally with npm so it lands in the system
# prefix and survives the home directory bind mount (same approach as
# pi's own docs/containerization.md)
RUN sudo npm install -g --ignore-scripts @earendil-works/pi-coding-agent && \
sudo npm cache clean --force
WORKDIR /home/${USERNAME}