# Story Kit – single-container runtime # All components (server, agents, web UI) run inside this container. # The target project repo is bind-mounted at /workspace. # # Build: docker build -t storkit -f docker/Dockerfile . # Run: docker compose -f docker/docker-compose.yml up # # Tested with: OrbStack (recommended on macOS), Docker Desktop (slower bind mounts) FROM rust:1.90-bookworm AS base # ── System deps ────────────────────────────────────────────────────── RUN apt-get update && apt-get install -y --no-install-recommends \ git \ curl \ ca-certificates \ build-essential \ pkg-config \ libssl-dev \ # cargo-nextest is a pre-built binary && rm -rf /var/lib/apt/lists/* # ── Node.js 22.x (matches host) ───────────────────────────────────── RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ && apt-get install -y --no-install-recommends nodejs \ && rm -rf /var/lib/apt/lists/* # ── cargo-nextest (test runner) ────────────────────────────────────── RUN curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C /usr/local/bin # ── Claude Code CLI ────────────────────────────────────────────────── # Claude Code is distributed as an npm global package. # The CLI binary is `claude`. RUN npm install -g @anthropic-ai/claude-code # ── Working directory ──────────────────────────────────────────────── # /app holds the storkit source (copied in at build time for the binary). # /workspace is where the target project repo gets bind-mounted at runtime. WORKDIR /app # ── Build the storkit server binary ───────────────────────────────── # Copy the full project tree so `cargo build` and `npm run build` (via # build.rs) can produce the release binary with embedded frontend assets. COPY . . # Build frontend deps first (better layer caching) RUN cd frontend && npm ci # Build the release binary (build.rs runs npm run build for the frontend) RUN cargo build --release \ && cp target/release/storkit /usr/local/bin/storkit # ── Runtime stage (smaller image) ─────────────────────────────────── FROM debian:bookworm-slim AS runtime RUN apt-get update && apt-get install -y --no-install-recommends \ git \ curl \ ca-certificates \ libssl3 \ # build-essential (gcc/cc) needed at runtime for: # - rebuild_and_restart (cargo build --release) # - agent-driven cargo commands (clippy, test, build) build-essential \ pkg-config \ libssl-dev \ && rm -rf /var/lib/apt/lists/* # Node.js in runtime RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ && apt-get install -y --no-install-recommends nodejs \ && rm -rf /var/lib/apt/lists/* # Claude Code CLI in runtime RUN npm install -g @anthropic-ai/claude-code # Cargo and Rust toolchain needed at runtime for: # - rebuild_and_restart (cargo build inside the container) # - Agent-driven cargo commands (cargo clippy, cargo test, etc.) COPY --from=base /usr/local/cargo /usr/local/cargo COPY --from=base /usr/local/rustup /usr/local/rustup ENV PATH="/usr/local/cargo/bin:${PATH}" ENV RUSTUP_HOME="/usr/local/rustup" ENV CARGO_HOME="/usr/local/cargo" # cargo-nextest COPY --from=base /usr/local/bin/cargo-nextest /usr/local/bin/cargo-nextest # The storkit binary COPY --from=base /usr/local/bin/storkit /usr/local/bin/storkit # Copy the full source tree so rebuild_and_restart can do `cargo build` # from the workspace root (CARGO_MANIFEST_DIR is baked into the binary). # Alternative: mount the source as a volume. COPY --from=base /app /app # ── Non-root user ──────────────────────────────────────────────────── # Claude Code refuses --dangerously-skip-permissions (bypassPermissions) # when running as root. Create a dedicated user so agents can launch. RUN groupadd -r storkit \ && useradd -r -g storkit -m -d /home/storkit storkit \ && mkdir -p /home/storkit/.claude \ && chown -R storkit:storkit /home/storkit \ && chown -R storkit:storkit /usr/local/cargo /usr/local/rustup \ && chown -R storkit:storkit /app # ── Entrypoint ─────────────────────────────────────────────────────── # Validates required env vars (GIT_USER_NAME, GIT_USER_EMAIL) and # configures git identity before starting the server. COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh USER storkit WORKDIR /workspace # ── Ports ──────────────────────────────────────────────────────────── # Web UI + MCP server EXPOSE 3001 # ── Volumes (defined in docker-compose.yml) ────────────────────────── # /workspace – bind mount: target project repo # /home/storkit/.claude – named volume: Claude Code sessions/state # /usr/local/cargo/registry – named volume: cargo dependency cache ENTRYPOINT ["entrypoint.sh"] CMD ["storkit", "/workspace"]