2026-03-21 20:19:56 +00:00
|
|
|
|
# Story Kit – single-container deployment
|
|
|
|
|
|
#
|
|
|
|
|
|
# Usage:
|
|
|
|
|
|
# # Set your API key and project path, then:
|
|
|
|
|
|
# ANTHROPIC_API_KEY=sk-ant-... PROJECT_PATH=/path/to/your/repo \
|
|
|
|
|
|
# docker compose -f docker/docker-compose.yml up
|
|
|
|
|
|
#
|
|
|
|
|
|
# OrbStack users: just install OrbStack and use `docker compose` normally.
|
|
|
|
|
|
# OrbStack's VirtioFS bind mount driver is significantly faster than
|
|
|
|
|
|
# Docker Desktop's default (see spike findings).
|
|
|
|
|
|
|
|
|
|
|
|
services:
|
|
|
|
|
|
storkit:
|
|
|
|
|
|
build:
|
|
|
|
|
|
context: ..
|
|
|
|
|
|
dockerfile: docker/Dockerfile
|
|
|
|
|
|
container_name: storkit
|
|
|
|
|
|
ports:
|
2026-03-21 20:33:50 +00:00
|
|
|
|
# Bind to localhost only — not exposed on all interfaces.
|
|
|
|
|
|
- "127.0.0.1:3001:3001"
|
2026-03-21 20:19:56 +00:00
|
|
|
|
environment:
|
|
|
|
|
|
# Required: Anthropic API key for Claude Code agents
|
|
|
|
|
|
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:?Set ANTHROPIC_API_KEY}
|
2026-03-21 20:33:50 +00:00
|
|
|
|
# Required: git identity for agent commits
|
|
|
|
|
|
- GIT_USER_NAME=${GIT_USER_NAME:?Set GIT_USER_NAME}
|
|
|
|
|
|
- GIT_USER_EMAIL=${GIT_USER_EMAIL:?Set GIT_USER_EMAIL}
|
2026-03-21 20:19:56 +00:00
|
|
|
|
# Optional: override the server port (default 3001)
|
|
|
|
|
|
- STORKIT_PORT=3001
|
|
|
|
|
|
# Optional: Matrix bot credentials (if using Matrix integration)
|
|
|
|
|
|
- MATRIX_HOMESERVER=${MATRIX_HOMESERVER:-}
|
|
|
|
|
|
- MATRIX_USER=${MATRIX_USER:-}
|
|
|
|
|
|
- MATRIX_PASSWORD=${MATRIX_PASSWORD:-}
|
|
|
|
|
|
# Optional: Slack webhook (if using Slack integration)
|
|
|
|
|
|
- SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN:-}
|
|
|
|
|
|
- SLACK_APP_TOKEN=${SLACK_APP_TOKEN:-}
|
|
|
|
|
|
volumes:
|
|
|
|
|
|
# The target project repo – bind-mounted from host.
|
|
|
|
|
|
# Changes made by agents inside the container are immediately
|
|
|
|
|
|
# visible on the host (and vice versa).
|
|
|
|
|
|
- ${PROJECT_PATH:?Set PROJECT_PATH}:/workspace
|
|
|
|
|
|
|
|
|
|
|
|
# Cargo registry cache – persists downloaded crates across
|
|
|
|
|
|
# container restarts so `cargo build` doesn't re-download.
|
|
|
|
|
|
- cargo-registry:/usr/local/cargo/registry
|
|
|
|
|
|
|
|
|
|
|
|
# Cargo git checkouts – persists git-based dependencies.
|
|
|
|
|
|
- cargo-git:/usr/local/cargo/git
|
|
|
|
|
|
|
|
|
|
|
|
# Claude Code state – persists session history, projects config,
|
|
|
|
|
|
# and conversation transcripts so --resume works across restarts.
|
2026-03-21 20:33:50 +00:00
|
|
|
|
- claude-state:/home/storkit/.claude
|
2026-03-21 20:19:56 +00:00
|
|
|
|
|
|
|
|
|
|
# Storkit source tree for rebuild_and_restart.
|
|
|
|
|
|
# The binary has CARGO_MANIFEST_DIR baked in at compile time
|
|
|
|
|
|
# pointing to /app/server, so the source must be at /app.
|
|
|
|
|
|
# This is COPY'd in the Dockerfile; mounting over it allows
|
|
|
|
|
|
# live source updates without rebuilding the image.
|
|
|
|
|
|
# Mount host source so rebuild_and_restart picks up live changes:
|
|
|
|
|
|
- ./..:/app
|
|
|
|
|
|
|
|
|
|
|
|
# Keep cargo build artifacts off the bind mount.
|
|
|
|
|
|
# Bind-mount directory traversal is ~23x slower than Docker volumes
|
|
|
|
|
|
# (confirmed in spike 329). Cargo stat-checks every file in target/
|
|
|
|
|
|
# on incremental builds — leaving it on the bind mount makes builds
|
|
|
|
|
|
# catastrophically slow (~12s just to traverse the tree).
|
|
|
|
|
|
- workspace-target:/workspace/target
|
|
|
|
|
|
- storkit-target:/app/target
|
|
|
|
|
|
|
2026-03-21 20:33:50 +00:00
|
|
|
|
# ── Security hardening ──────────────────────────────────────────
|
|
|
|
|
|
# Read-only root filesystem. Only explicitly mounted volumes and
|
|
|
|
|
|
# tmpfs paths are writable.
|
|
|
|
|
|
read_only: true
|
|
|
|
|
|
tmpfs:
|
|
|
|
|
|
- /tmp:size=512M
|
2026-03-21 21:19:16 +00:00
|
|
|
|
- /home/storkit:size=512M,uid=999,gid=999
|
2026-03-21 20:33:50 +00:00
|
|
|
|
|
|
|
|
|
|
# Drop all Linux capabilities, then add back only what's needed.
|
2026-03-21 21:16:24 +00:00
|
|
|
|
# SETUID/SETGID needed by Claude Code's PTY allocation (openpty).
|
2026-03-21 20:33:50 +00:00
|
|
|
|
cap_drop:
|
|
|
|
|
|
- ALL
|
2026-03-21 21:16:24 +00:00
|
|
|
|
cap_add:
|
|
|
|
|
|
- SETUID
|
|
|
|
|
|
- SETGID
|
2026-03-21 20:33:50 +00:00
|
|
|
|
|
|
|
|
|
|
# Prevent child processes from gaining new privileges via setuid,
|
|
|
|
|
|
# setgid, or other mechanisms.
|
|
|
|
|
|
security_opt:
|
|
|
|
|
|
- no-new-privileges:true
|
|
|
|
|
|
|
2026-03-21 20:19:56 +00:00
|
|
|
|
# Resource limits – cap the whole system.
|
|
|
|
|
|
# Adjust based on your machine. These are conservative defaults.
|
|
|
|
|
|
deploy:
|
|
|
|
|
|
resources:
|
|
|
|
|
|
limits:
|
|
|
|
|
|
cpus: "4"
|
|
|
|
|
|
memory: 8G
|
|
|
|
|
|
reservations:
|
|
|
|
|
|
cpus: "1"
|
|
|
|
|
|
memory: 2G
|
|
|
|
|
|
|
|
|
|
|
|
# Health check – verify the MCP endpoint responds
|
|
|
|
|
|
healthcheck:
|
|
|
|
|
|
test: ["CMD", "curl", "-sf", "http://localhost:3001/health"]
|
|
|
|
|
|
interval: 30s
|
|
|
|
|
|
timeout: 5s
|
|
|
|
|
|
retries: 3
|
|
|
|
|
|
start_period: 10s
|
|
|
|
|
|
|
|
|
|
|
|
# Restart policy – restart on crash but not on manual stop
|
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
|
|
|
|
|
|
|
volumes:
|
|
|
|
|
|
cargo-registry:
|
|
|
|
|
|
cargo-git:
|
|
|
|
|
|
claude-state:
|
|
|
|
|
|
workspace-target:
|
|
|
|
|
|
storkit-target:
|