Files
zopu-code/packages/agents/Dockerfile.runner
-Puter 4dc878b8cb fix(agents): bundle workspace deps into flue runtime
Replace @code/env and @code/primitives imports with local modules so
the Node deploy artifact does not resolve workspace packages to
TypeScript source at runtime. Switch Docker build to pnpm frozen
install, add runner Dockerfile and a liveness health endpoint.
2026-08-01 20:17:49 +05:30

85 lines
3.1 KiB
Docker

# syntax=docker/dockerfile:1.7
#
# AgentOS runner image for the VDS Compose topology.
#
# This image is distinct from the production Flue image (Dockerfile): it is the
# dedicated runner that registers with the Rivet Engine and owns the persistent
# host filesystem used to clone repositories, install dependencies, and mount
# isolated checkouts into AgentOS workspaces. It needs Bun + Git + the engine-cli
# used by local development, plus Node (required by the Flue/AgentOS runtime).
#
# The runner is internal-only. It never publishes a port; only the engine and
# Compose healthcheck reach it. Secrets are injected at runtime via the Compose
# environment, never baked into a layer.
#
# RIVET_RUNNER_VERSION is a build-time contract: it lets the engine route new
# actors to the new runner and drain old ones. CI sets it to the release
# identity (commit SHA or build timestamp) for every immutable image it pushes.
FROM oven/bun:1.3.14 AS bun
FROM node:24-bookworm-slim AS build
# Bun is needed to install dependency trees in the cloned workspaces.
COPY --from=bun /usr/local/bin/bun /usr/local/bin/bun
WORKDIR /app
# Native build toolchain for optional native deps during install.
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
g++ \
make \
python3 \
&& rm -rf /var/lib/apt/lists/*
# pnpm-lock.yaml is authoritative; Bun would migrate it and reject frozen mode.
RUN npm install --global pnpm@11.17.0
COPY . .
RUN pnpm install --frozen-lockfile
# Runner image only. No Flue server build is needed: the runner entry point
# (src/runner.ts) calls runtimeRegistry.startAndWait() to register with the
# engine. Building the Flue Node server here would be dead weight.
FROM node:24-bookworm-slim AS runner
# Git and CA certs are required by RepositoryWorkspace to clone user repos and
# install dependencies inside the mounted source mirror.
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
git \
openssh-client \
&& rm -rf /var/lib/apt/lists/* \
&& git --version
# Carry Bun into the runtime image so `bun install --frozen-lockfile` works on
# cloned checkouts and BUN_EXECUTABLE resolves to a known path.
COPY --from=bun /usr/local/bin/bun /usr/local/bin/bun
ARG RIVET_RUNNER_VERSION
ENV RIVET_RUNNER_VERSION=${RIVET_RUNNER_VERSION}
ENV NODE_ENV=production
WORKDIR /app
COPY --from=build /app /app
# Non-root runtime. Compose mounts the workspace bind directory initialized for
# this UID so the process can serve its isolated worktrees.
RUN groupadd --system --gid 10001 zopu \
&& useradd --system --uid 10001 --gid zopu --create-home --home-dir /home/zopu zopu \
&& mkdir -p /var/lib/zopu/workspaces \
&& chown -R zopu:zopu /var/lib/zopu /home/zopu
# Point the runtime at the Bun executable discovered by RepositoryWorkspace.
# /home/zopu is the pi agent home mount target used by attempt-runner.ts.
ENV BUN_EXECUTABLE=/usr/local/bin/bun \
AGENT_WORKSPACE_ROOT=/var/lib/zopu/workspaces
USER zopu
# runner.ts is TypeScript and this repository executes it with Bun locally.
CMD ["bun", "packages/agents/src/runner.ts"]