71 lines
2.5 KiB
Docker
71 lines
2.5 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): `bunx` runs the stdio MCP servers declared in
|
|
# the user's config. The claude CLI itself ships inside the
|
|
# claude-agent-sdk wheel (`_bundled/claude`), nothing to install here.
|
|
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
|
|
|
|
# The model process runs as `beaver-runner`, not as the gateway: the
|
|
# adapter spawns claude under this uid with a whitelisted environment.
|
|
# `acl` lets the entrypoint grant it write access to the vault sub-mounts
|
|
# without chowning files that Obsidian Sync keeps rewriting as root.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends acl \
|
|
&& rm -rf /var/lib/apt/lists/* \
|
|
&& useradd --system --uid 1001 --create-home --shell /usr/sbin/nologin beaver-runner
|
|
|
|
ENV PATH=/app/.venv/bin:$PATH
|
|
|
|
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"]
|