Files
beaver-gateway/Dockerfile
T
hhandClaude Fable 5 e4282b38cd feat(ui,infra): SvelteKit ui scaffold, Makefile, pre-commit, claude hooks
ui/: SvelteKit 2 + Svelte 5 + Tailwind 4 + shadcn-svelte (luma, lucide)
on bun with ultracite; adapter-static with SPA fallback; theme tokens
taken from msos. Dockerfile gains a bun stage that builds ui/build.
Makefile and pre-commit cover ruff, ty, ultracite and svelte-check;
.claude settings run the matching fixer after edits. docs/PRODUCT.md
captures product truth for the UI work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 23:22:18 +02:00

75 lines
2.9 KiB
Docker

# syntax=docker/dockerfile:1.7
#
# Two stages: a uv-based builder that resolves the venv, and a thin
# python:3.13-slim runtime with bun + the `claude` CLI baked in.
#
# Alpine is intentionally avoided: @anthropic-ai/claude-code ≥ 2.1.113
# ships a glibc-only native binary (anthropics/claude-code#50270).
#
# This image is deliberately un-opinionated about ports and command —
# the consumer's compose file decides what to publish and how to invoke.
# ---- Builder: uv + Python deps ----
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS builder
ENV UV_LINK_MODE=copy \
UV_COMPILE_BYTECODE=1 \
UV_PYTHON_DOWNLOADS=never
# `git` is required at build time: the `prod` extra resolves
# raycast-api / claude-code-api from git URLs.
RUN apt-get update \
&& apt-get install -y --no-install-recommends git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen --no-dev --no-install-project --extra prod
COPY . /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev --extra prod
# ---- UI: SvelteKit SPA built with bun ----
FROM oven/bun:1-slim AS ui
WORKDIR /ui
COPY ui/package.json ui/bun.lock ./
RUN bun install --frozen-lockfile
COPY ui ./
RUN bun --bun svelte-kit sync && bun --bun run build
# ---- Runtime ----
FROM python:3.13-slim AS runtime
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates git \
&& rm -rf /var/lib/apt/lists/*
# Bun native binary (glibc) — fast `npm install` replacement, only used
# to drop the claude CLI into the image. Not invoked at runtime.
COPY --from=oven/bun:1-slim /usr/local/bin/bun /usr/local/bin/bun
RUN ln -s /usr/local/bin/bun /usr/local/bin/bunx
# `--trust` is required: without it bun skips the postinstall step that
# fetches claude's native binary (anthropics/claude-code#50203). The
# postinstall itself is bun's smoke check — if it fails the layer
# fails. We deliberately DO NOT run `claude --version` here: claude
# touches `$HOME` on every invocation (creates `/root/.claude/`,
# `/root/.claude.json`, sometimes `/root/.config/claude/`), and those
# build-time artifacts seed the runtime named-volume `claude-home`
# with stale "haven't onboarded" state, so the user gets re-prompted
# for trust/bypass dialogs on every rebuild and the subscription auth
# can land on a tainted credential file.
ENV BUN_INSTALL=/usr/local/bun-global \
PATH=/usr/local/bun-global/bin:/app/.venv/bin:$PATH
RUN bun install -g --trust @anthropic-ai/claude-code \
&& test -x "$(command -v claude)" \
&& rm -rf /root/.claude /root/.claude.json /root/.config/claude
COPY --from=builder /app/.venv /app/.venv
COPY --from=builder /app /app
COPY --from=ui /ui/build /app/ui/build
WORKDIR /app
ENTRYPOINT ["python", "-m"]
CMD ["beaver_gateway"]