# Minimal Mosaic Stack POC agent image. # Base: maintained Node.js image (same family as Pi's documented # containerization example in docs/containerization.md). FROM node:24-bookworm-slim # Tools Pi's documented container image expects (bash, CA certs, git, ripgrep). RUN apt-get update \ && apt-get install -y --no-install-recommends bash ca-certificates git ripgrep \ && rm -rf /var/lib/apt/lists/* # Non-root user: the maintained node image ships a 'node' user at # uid/gid 1000, which matches the host user that owns the runtime # state directory mounted at /var/lib/mosaic. It is reused as-is. # Pinned Pi install: package.json pins the exact version and # package-lock.json is installed with npm ci. No unversioned installs. WORKDIR /opt/app COPY package.json package-lock.json ./ RUN npm ci --ignore-scripts # Immutable contract fixtures (required location) and runtime scripts. COPY contracts /opt/mosaic/contracts COPY src /opt/mosaic/src RUN chmod 0555 /opt/mosaic/contracts /opt/mosaic/contracts/* \ && chmod 0555 /opt/mosaic/src /opt/mosaic/src/*.sh # Writable state, workspace, and pi agent directory (auth.json is # bind-mounted read-only at runtime; nothing is copied into the image). RUN mkdir -p /var/lib/mosaic /workspace /home/node/.pi/agent \ && chown -R node:node /var/lib/mosaic /workspace /home/node /opt/app USER node WORKDIR /workspace ENV HOME=/home/node \ PATH="/opt/app/node_modules/.bin:${PATH}" \ PI_OFFLINE=1 # One-shot agent: args form the user request (default is the startup # verification request defined in compose.yaml). ENTRYPOINT ["/opt/mosaic/src/run-agent.sh"]