# Pristine clean-room image for testing/recording Open Walnut's first-run onboarding. # # Why a dedicated image: the dev's Mac is "polluted" — a real AWS_BEARER_TOKEN_BEDROCK in # the shell and a populated ~/.claude — so it can never honestly show the new-user flow. # A container gives a guaranteed-empty home (fresh ~/.claude, no AWS env, empty # ~/.open-walnut) where the onboarding banner actually fires. # # It builds the app fresh inside the image, the README's checkout route: bun only, no # Node anywhere in the image (`bun install`, `bun run web:build`, `bun dist/cli.js web`). # Search/embedding is disabled (WALNUT_DISABLE_SEARCH=1) so no 1.16GB model download. # # Build: docker build -f Dockerfile.onboarding -t walnut-onboarding . # Run : docker run --rm -p 3457:3457 walnut-onboarding # path 1/3: no creds # docker run --rm -p 3457:3457 \ # -e AWS_BEARER_TOKEN_BEDROCK=... -e AWS_REGION=us-west-2 \ # walnut-onboarding # path 2 happy-path # # The container CANNOT touch the production server on :3456 — separate kernel namespace, # separate home, separate port. Nothing is mounted from the host. FROM debian:bookworm-slim # git for the skill demo. No compiler: Walnut has no native module that builds on # install (SQLite and the terminal are bun's own), and every native dependency it # has ships a prebuilt binary. RUN apt-get update && apt-get install -y --no-install-recommends \ git ca-certificates curl \ && rm -rf /var/lib/apt/lists/* # The only runtime: bun, at the version package.json pins (packageManager). COPY --from=oven/bun:1.4.4 /usr/local/bin/bun /usr/local/bin/bun # Run as a non-root user with a fresh, empty HOME → fresh ~/.claude + ~/.open-walnut. RUN useradd -m -u 10001 walnut USER walnut WORKDIR /home/walnut/app # Install backend deps first (layer cache). Copy package manifests and lockfiles only. COPY --chown=walnut:walnut package.json bun.lock bunfig.toml ./ COPY --chown=walnut:walnut packages/plugin-api/package.json ./packages/plugin-api/ COPY --chown=walnut:walnut packages/plugin-cli/package.json ./packages/plugin-cli/ COPY --chown=walnut:walnut web/package.json web/bun.lock ./web/ # Bun applies patches/; postinstall needs scripts/. With src/ not copied yet the # postinstall takes the installed-package route, so web/ is installed here. COPY --chown=walnut:walnut patches ./patches COPY --chown=walnut:walnut scripts ./scripts RUN bun install --frozen-lockfile && cd web && bun install --frozen-lockfile # Copy the rest of the source and build (server → dist/, SPA → web/dist/). COPY --chown=walnut:walnut . . RUN bun run web:build # Clean-room runtime env: # - empty HOME means ~/.claude and ~/.aws don't exist → resolver finds nothing → onboarding fires # - no AWS_*/ANTHROPIC_* baked in (pass at `docker run -e` only for the happy-path demo) # - search disabled so boot is fast and the image stays lean ENV WALNUT_DISABLE_SEARCH=1 \ PORT=3457 \ NODE_ENV=production EXPOSE 3457 # Serve the prebuilt dist on :3457 with bun. (web:build already ran above, so just run the server.) CMD ["bun", "dist/cli.js", "web", "--port", "3457"]