# syntax=docker/dockerfile:1 # # Ori sandbox template: the ori web application packaged on top of the # official Docker Sandboxes claude-code template, so the sandbox ships both # Claude Code and the ori server that fronts it over ACP. # # Build from the repository root (the ui and Go sources are the context): # # docker build -f template/Dockerfile -t k33g/ori . # # In a sandbox the runtime replaces CMD with its own process manager; the ori # kit (kits/ori/spec.yaml) is what starts the server. The CMD below makes the # image also work standalone (docker run -p 8888:8888 k33g/ori). ARG GO_VERSION=1.26 ARG NODE_VERSION=24 ############################# # Frontend build (Vite SPA) # ############################# # --platform=$BUILDPLATFORM: the SPA build is platform-independent, so it runs # once, natively. Without this, the amd64 half of a multi-arch build runs Vite # under qemu on an arm64 host — where bundling Monaco exhausts Node's heap. FROM --platform=$BUILDPLATFORM node:${NODE_VERSION}-bookworm AS ui-builder WORKDIR /src/ui COPY ui/package.json ui/package-lock.json ./ RUN npm ci COPY ui/ ./ # prebuild copies the Material icons into public/, then Vite builds to dist/ RUN npm run build #################### # Go backend build # #################### # Also native: Go cross-compiles to the target with GOOS/GOARCH, no qemu. FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm AS go-builder ARG TARGETOS ARG TARGETARCH WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY cmd/ ./cmd/ COPY internal/ ./internal/ COPY ui/embed.go ./ui/ COPY --from=ui-builder /src/ui/dist ./ui/dist RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -trimpath -o /out/ori ./cmd/ori \ && CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -trimpath -o /out/ori-mock-agent ./cmd/ori-mock-agent ############################################################## # Claude Code ACP adapter, fetched natively then copied over # ############################################################## # Installed in a $BUILDPLATFORM stage (the package is JavaScript, and its # vendored binaries ship for every platform) so the final stage needs no RUN # at all — a multi-arch build never touches qemu. FROM --platform=$BUILDPLATFORM node:${NODE_VERSION}-bookworm AS adapter RUN npm install -g --prefix /adapter @zed-industries/claude-code-acp ################################################### # Final image: claude-code sandbox template + ori # ################################################### FROM docker/sandbox-templates:claude-code # The adapter lands in the template's npm prefix, which is agent-owned and on # PATH — so `claude-code-acp` resolves and the sandbox never needs npx to # download it at runtime. COPY --from=adapter --chown=agent:agent /adapter/ /usr/local/share/npm-global/ COPY --from=go-builder /out/ori /out/ori-mock-agent /usr/local/bin/ # ori listens here; publish it from the host with: # sbx ports --publish 8888:8888/tcp EXPOSE 8888 # Standalone-run default. Inside a sandbox the ori kit starts the server # instead (the runtime overrides CMD with its own supervisor). CMD [ "ori", "--addr", ":8888", "--agent-cmd", "claude-code-acp", "--cwd", "/home/agent/workspace" ]